perm filename IOSER.TNX[10X,AIL]24 blob sn#344493 filedate 1978-03-27 generic text, type T, neo UTF8
00100	COMMENT ⊗   VALID 00112 PAGES
00200	C REC  PAGE   DESCRIPTION
00300	C00001 00001
00400	C00010 00002	TENX<THE ENTIRE FILE IS FOR TENEX ONLY
00500	C00013 00003	DSCR IOSTT(CDB) values.
00600	C00016 00004
00700	C00020 00005	COMPIL(PAT,<OPEN,LOOKUP,ENTER,USETI,USETO,MTAPE,TENXFI,RELEASE,CLOSE,CLOSIN,CLOSO,GETCHAN,CVJFN,RENAME>
00800	C00029 00006	DSCR  PROCEDURE LOOKUP(INTEGER CHNL STRING FILE REFERENCE INTEGER FLAG)
00900	C00033 00007	HERE(ENTER)
01000	C00036 00008	DSCR
01100	C00039 00009	DSCR PROCEDURE USETI,USETO(INTEGER CHANNEL,BLOCK)
01200	C00041 00010	DSCR	PROCEDURE CLOSE(INTEGER CHANNEL,[CLOSE_INHIBIT_BITS])
01300	C00042 00011	HERE(RELEASE)
01400	C00043 00012	DSCR	
01500	C00044 00013	DSCR	STRING PROCEDURE TENXFI(STRING DECFILE)
01600	C00048 00014	DSCR
01700	C00050 00015	COMPIL(JOBINF,<ODTIM,IDTIM,RUNTM,GTAD,GJINF>,<ZSETST,ZADJST,X22,X33,X44,.SKIP.,CATCHR>
01800	C00051 00016
01900	C00052 00017	DSCR INTEGER SIMPLE PROCEDURE RUNTM(INTEGER FORK REFERENCE INTEGER CONSOLE)
02000	C00053 00018	DSCR INTEGER SIMPLE PROCEDURE GTAD
02100	C00054 00019	DSCR INTEGER SIMPLE PROCEDURE GJINF(REFERENCE INTEGER LOGDIR,CONDIR,TTYNO)
02200	C00055 00020	ENDCOM(JOBINF)
02300	C00056 00021	COMPIL(DIRECT,<STDIR,DIRST>,<X22,X33,CATCHR,ZSETST,ZADJST.SKIP.>
02400	C00058 00022	DSCR STRING SIMPLE PROCEDURE DIRST(INTEGER I)
02500	C00060 00023	COMPIL(RUNPRG,<RUNPRG>,<X22,X33,CATCHR>,<RUNPRG -- RUN A PROGRAM>)
02600	C00065 00024	COMPIL(OPF,<OPENFILE,SETINPUT,SETPL,INDEXFILE,SETCHAN>,<.SKIP.>,<OPENFILE -- OPEN A FILE>)
02700	C00074 00025	DSCR PROCEDURE SETINPUT(INTEGER CHAN REFERENCE INTEGER COUNT,BR,EOF)
02800	C00075 00026	DSCR
02900	C00077 00027	DSCR
03000	C00079 00028	DSCR SETCHAN(JFN,GTFLAGS,OPFLAGS)
03100	C00080 00029	COMPIL(GTJFN,<GTJFN,GTJFNL>,<.SKIP.,SETCHN,CATCHR,X11,X22,X44>,<GTJFN -- GET A JFN>)
03200	C00082 00030	DSCR INTEGER PROCEDURE GTJFNL(STRING ORIG INTEGER FLAGS, XWDJFN!JFN
03300	C00085 00031	COMPIL(FILINF,<GNJFN,DELF,UNDELETE,DELNF,SIZEF,JFNS,JFNSL,OPENF,CFILE,CLOSF,RLJFN,GTSTS,STSTS,RNAMF>
03400	C00087 00032	DSCR	PROCEDURE DELF(INTEGER CHAN)
03500	C00089 00033	DSCR	PROCEDURE UNDELETE(INTEGER CHAN)
03600	C00090 00034	DSCR	INTEGER PROCEDURE SIZEF(INTEGER JFN)
03700	C00091 00035
03800	C00093 00036	DSCR SIMPLE PROCEDURE OPENF(INTEGER JFN,FLAGS)
03900	C00095 00037
04000	C00098 00038	DSCR SIMPLE PROCEDURE CLOSF(INTEGER JFN)
04100	C00100 00039	DSCR SIMPLE PROCEDURE RLJFN(INTEGER JFN)
04200	C00101 00040	DSCR INTEGER SIMPLE PROCEDURE GTSTS(INTEGER JFN)
04300	C00102 00041	DSCR BOOLEAN SIMPLE PROCEDURE STSTS(INTEGER JFN,STATUS)
04400	C00103 00042	DSCR BOOLEAN SIMPLE PROCEDURE RNAMF(INTEGER EXISTINGJFN,NEWJFN)
04500	C00104 00043	COMPIL(DEVINF,<CNDIR,ASND,RELD,GDSTS,SDSTS,STDEV,DEVST,GTFDB,CHFDB>
04600	C00106 00044	DSCR BOOLEAN PROCEDURE ASND(INTEGER DEVICE)
04700	C00107 00045	DSCR BOOLEAN PROCEDURE RELD(INTEGER DEVICE)
04800	C00108 00046	DSCR INTEGER SIMPLE PROCEDURE GDSTS(INTEGER CHAN REFERENCE INTEGER WORDCNT)
04900	C00109 00047	DSCR PROCEDURE SDSTS(INTEGER JFN,NEWSTATUS)
05000	C00110 00048	DSCR INTEGER PROCEDURE STDEV(STRING S)
05100	C00111 00049
05200	C00112 00050	DSCR	SIMPLE PROCEDURE GTFDB(INTEGER JFN REFERENCE INTEGER ARRAY BUF)
05300	C00113 00051
05400	C00114 00052	DSCR INTEGER SIMPLE PROCEDURE WORDIN(INTEGER JFN)
05500	C00116 00053	HERE(ARRYIN)
05600	C00120 00054	HERE(WORDOUT)
05700	C00122 00055	HERE(ARRYOUT)
05800	C00125 00056
05900	C00127 00057	HERE(SWDPTR)
06000	C00129 00058
06100	C00136 00059	SETWPT:
06200	C00140 00060	SETWIO:
06300	C00141 00061	ADWI:	
06400	C00143 00062	DSCR  CHAR←CHARIN(CHANNEL)
06500	C00146 00063	DSCR STRING SIMPLE PROCEDURE SINI(INTEGER JFN,MAXLENGTH,BRKCHAR)
06600	C00150 00064	Input 
06700	C00158 00065	.DOINP:	PUSHJ	P,DOINP
06800	C00159 00066
06900	C00163 00067	Realin, Realscan 
07000	C00170 00068	NUMIN -- CONTD.
07100	C00177 00069	LNUMIN	NUMBER INPUT
07200	C00188 00070
07300	C00190 00071	DSCR DATA TABLES FOR REALIN, INTSCAN, ETC.
07400	C00191 00072
07500	C00193 00073
07600	C00196 00074	DSCR	PROCEDURE LINOUT(INTEGER JFN,VALUE)
07700	C00199 00075	HERE(RCHPTR)
07800	C00200 00076	HERE(SCHPTR)
07900	C00202 00077	DSCR	Auxiliary routines for character i/o.
08000	C00208 00078	SETCPT:
08100	C00211 00079	SETCIO:
08200	C00212 00080	DSCR
08300	C00225 00081	DSCR 	ADCO,ADCO1
08400	C00229 00082	DSCR SETIO
08500	C00236 00083	DSCR
08600	C00239 00084	ENDCOM(IOROU)
08700	C00240 00085	DSCR SIMPLE PROCEDURE SFPTR(INTEGER JFN,POINTER)
08800	C00241 00086	DSCR INTEGER SIMPLE PROCEDURE RFPTR(INTEGER JFN)
08900	C00242 00087	DSCR SIMPLE PROCEDURE MTOPR(INTEGER JFN,FUNCTION,VALUE)
09000	C00243 00088	DSCR SIMPLE PROCEDURE BKJFN(INTEGER JFN)
09100	C00244 00089	DSCR INTEGER SIMPLE PROCEDURE RFBSZ(INTEGER JFN)
09200	C00245 00090	COMPIL(DSKOPS,<DSKIN,DSKOUT>
09300	C00247 00091	DSCR SIMPLE PROCEDURE 
09400	C00248 00092	COMPIL(DEVS,<DEVTYPE,DVCHR,ERSTR>
09500	C00249 00093	DSCR INTEGER SIMPLE PROCEDURE DVCHR(INTEGER JFN REFERENCE INTEGER AC1,AC3)
09600	C00250 00094	DSCR SIMPLE PROCEDURE ERSTR(INTEGER ERRNO,FORK)
09700	C00252 00095	COMPIL(UTILITY,<SETCHN,ZSETST,ZADJST,.RESET,RDSEG>
09800	C00258 00096	DSCR STRING SIMPLE PROCEDURE ZADJST(INTEGER CNTEST,BP)
09900	C00261 00097	DSCR
10000	C00265 00098	COMPIL(TTM,<RFMOD,SFMOD,STPAR,STI,RFCOC,SFCOC,GTTYP,STTYP,SETEDIT>
10100	C00271 00099	COMPIL(PAGES,<PMAP>,<SAVE,RESTR,X44>
10200	C00272 00100	COMPIL(TT2,<PBTIN,INTTY>
10300	C00273 00101	DSCR STRING SIMPLE PROCEDURE INTTY
10400	C00275 00102	NOIMSSS<NON-IMSSS VERSION OF INTTY FOR THOSE WHO SUFFER
10500	C00279 00103	 TTY FUNCTIONS 
10600	C00282 00104	HERE(PBIN)
10700	C00292 00105	Filnam 
10800	C00295 00106	Flscan 
10900	C00297 00107	COMPIL(CAS,<CSERR,LPRYER>,<GOGTAB>
11000	C00298 00108	
11100	C00299 00109
11200	C00300 00110
11300	C00301 00111
11400	C00302 00112
11500	C00303 ENDMK
11600	C⊗;
     

00100	TENX<;THE ENTIRE FILE IS FOR TENEX ONLY
00200	COMMENT ⊗ TENEX-IOSER -- R. SMITH ⊗
00300		LSTON	(IOSER)
00400	
00500	
00600	IFN ALWAYS, <BEGIN IOSER>
00700	
00800	COMMENT ⊗ INDICES, BITS FOR TENEX VERSION OF IOSER ⊗
00900	
01000	
01100	;WORDS IN CDB BLOCK FOR EACH CHANNEL
01200	
01300	
01400	?GFL←←0				;FLAGS FOR GTJFN
01500	?OFL←←1				;FLAGS FOR OPENF
01600	?BRCHAR←←2			;BRCHAR ADDRESS
01700	?ICOUNT←←3			;COUNT ADDRESS
01800	?ENDFL←←4			;EOF ADDRESS
01900	?IOCNT←←5			;I/O COUNT
02000	?IOBP←←6			;I/O BP
02100	?IOSTT←←7			;STATUS OF THE IO (SEE FLAGS BELOW)
02200	?IOADDR←←10			;ADDRESS OF THE IO BUFFER IF THERE IS ONE
02300	?DVTYP←←11				;DEVICE TYPE
02400	?DVDSG←←12			;DEVICE DESIGNATOR
02500	?OPNDUN←←13			;TRUE IF OPENED WITH THE OPEN STATEMENT
02600	?DVCH←←14			;DEVICE CHARACTERISTICS
02700	?DMPED←←15			;TRUE IF DUMP MODE OUTPUT SEEN
02800					;IN PARTICULAR USED TO NOTE IF A MAGTAPE
02900					;HAS BEEN WRITTEN BUT NOT YET CLOSED,
03000					;SINCE EOF'S ARE WRITTEN AT THE CLOSE
03100					;BY CLOSF,CFILE,CLOSE,ETC.
03200	?LINNUM←←16			;LINE NO (FOR INPUT FUNCTION)
03300	?PAGNUM←←17			;PAGE NO (FOR INPUT FUNCTION)
03400	?SOSNUM←←20			;SOS LINE NO (FOR INPUT FUNCTION)
03500	?FKPAGE←←21			;XWD FORK,PAGE FOR PMAPPING TO DSK
03600	?IOPAGE←←22			;PAGE OF THE FILE (IF PMAPPED)
03700	?FDBSZ←←23			;BYTE SIZE OF FILE AS IN FDB
03800	?FDBEOF←←24			;NO. OF BYTES TO EOF AS IN FDB
03900	?TTYINF←←25			;TTY BUFFERING INFO--
04000	
04100	;ADDITIONS TO CDB NUMBERS SHOULD INCLUDE CHANGE TO IOTLEN BELOW
04200	
04300	?IOTLEN←←26			;CURRENT LENGTH OF CDB BLOCK
04400	
     

00100	DSCR IOSTT(CDB) values.
00200		The following numbers can be in IOSTT(CDB).  They indicate
00300	the current state of the IO for the associated channel.
00400		These numbers are set up by SETIO, which is called by
00500	the first IO that happens on the channel.  Each routine has
00600	a dispatch table, usually called TABL, and the SIMIO macro
00700	does an XCT on those tables.
00800	⊗
00900	
01000	?XNULL←←0			;NOTHING HAPPENING YET
01100	?XICHAR←←1			;PMAPPING INPUT CHARS
01200	?XOCHAR←←2			;PMAPPING OUTPUT CHARS
01300	?XIWORD←←3			;PMAPPING INPUT WORDS
01400	?XOWORD←←4			;PMAPPING OUTPUT WORDS
01500	?XCICHAR←←5			;36 BIT BUFFERING, INPUT CHARS
01600	?XCOCHAR←←6			;36 BIT BUFFERING, OUTPUT CHARS
01700	?XCIWORD←←7			;36 BIT BUFFERING, INPUT OR OUTPUT WORDS
01800	?XBYTE7←←10			;7 BIT BIN, SIN ETC
01900	?XDICHAR←←11			;DUMP MODE CHARACTER INPUT
02000	?XDOCHAR←←12			;DUMP MODE CHARACTER OUTPUT
02100	?XDARR←←13			;DUMP MORE ARRAY INPUT OR OUTPUT
02200	
02300	DEFINE SIMIO(AC,TABL,ERR) <
02400		SKIPGE	AC,IOSTT(CDB)	
02500		  JRST [PUSHJ	P,OPNCHK
02600			MOVE	AC,IOSTT(CDB)	
02700			JRST	.+1]
02800		CAILE	AC,13		;MAXIMUM THAT IOSTT CAN BE
02900		  JRST	ERR
03000		XCT	TABL(AC)
03100	>;SIMIO
03200	
03300	DEFINE CHKDECCLZ <
03400		SKIPGE	IOSTT(CDB)
03500		  PUSHJ P,OPNCHK
03600	>;CHKDECCLZ
03700	
03800	DEFINE SETZEOF <
03900		SETZM	.SKIP.
04000		SKIPE	ENDFL(CDB)
04100		  SETZM	@ENDFL(CDB)
04200	>;SETZEOF
04300	
04400	DEFINE SETOEOF <
04500		SETOM	.SKIP.
04600		SKIPE	ENDFL(CDB)
04700		  SETOM	@ENDFL(CDB)
04800	>;SETOEOF
04900	
05000	
     

00100	
00200	IFNDEF JFNSIZE, <?JFNSIZE←←20>			;NUMBER OF CHANNELS ALLOWED
00300	?DMOCNT←←200			;(DEFAULT) COUNT FOR DUMP MODE OUTPUT
00400	IFNDEF STARTPAGE,<?STARTPAGE←←610			;STARTING PAGE FOR BUFFERS>
00500	
00600	;BITS FOR SCAN FLAGS FOR OPENFILE ROUTINE
00700	;THE BITS OF THE FLAGS WORD ARE THE SAME AS THE BITS OF GTJFN AND OPENF
00800	;HOPEFULLY (WHERE APPLICABLE)
00900	
01000	?STARBIT←←1B11			;B11 OF GTJFN FOR INDEXED FILES
01100	?TEMBIT←←1B5			;B5 OF GTJFN FOR TEMPORARY FILE
01200	?DELBIT←←1B8			;GTJFN -- IGNORE DELETED BIT
01300	?RDBIT←←1B19			;B19 OF OPENF FOR READING
01400	?WRBIT←←1B20			;B20 OF OPENF FOR WRITING
01500	?APPBIT←←1B22			;B22 OF OPENF FOR APPEND
01600	?CONFB1←←1B3			;GTJFN BIT TO PRINT [CONFIRM] ETC
01700	?CONFB2←←1B4			;GTJFN BIT TO REQUIRE CONFIRMATION FROM USER
01800					;ODDLY ENOUGH 3 AND 4 ARE ILLEGAL
01900	?OUTBIT←←1B0			;GTJFN -- FILE FOR OUTPUT USE
02000	?OLDBIT←←1B2			;GTJFN -- OLD FILE
02100	?NEWBIT←←1B1			;GTJFN -- NEW FILE
02200	?ERTNBIT←←1B27			;ERROR RETURN BIT -- INTERNAL
02300	?BINBIT←←1B26			;BINARY BIT -- INTERNAL
02400	?THAWBIT←←1B25			;THAWBIT GTJFN
02500	?ERSNBIT←←1B28			;ERROR SEEN -- INTERNAL
02600	?CONFBIT←←1B29			;CONFIRMATION -- INTERNAL
02700	
02800	;MACROS FOR BIT TESTING
02900	
03000	DEFINE .ZZZ $ (X,Y,Z)<
03100	IFN Z&777777000000, <TL$X Y,Z⊗-=18>	;Z LSH -=18
03200	IFN Z&777777, <TR$X Y,Z>
03300	>
03400	
03500	DEFINE TESTE (Y,Z) <.ZZZ NE,Y,Z>	;TDNE Y,[Z]
03600	DEFINE TESTN (Y,Z) <.ZZZ NN,Y,Z>	;TDNN Y,[Z]
03700	DEFINE TESTO (Y,Z) <.ZZZ O,Y,Z>		;TDO Y,[Z]
03800	DEFINE TESTZ (Y,W) <.ZZZ Z,Y,W>		;TDZ Y,[Z]
03900	
04000	
04100	;MACRO TO GET THE JFN NUMBER IN X FROM Y.  IF INVALID, JUMP TO LABEL Z
04200	;LOADS CDB (I.E., 11) WITH THE CDB ADDRESS
04300	;LOADS CHNL WITH THE CHANNEL NUMBER
04400	DEFINE VALCHN(X,Y,Z) <
04500	
04600		SKIPL	CHNL,Y
04700		CAIL	CHNL,JFNSIZE
04800		  JRST	Z	
04900		MOVE	CDB,CDBTBL(CHNL)
05000		HRRZ	X,JFNTBL(CHNL)
05100		JUMPE	X,Z
05200	>;VALCHN
05300		
05400	DEFINE LITCHN(X,Y,Z) <
05500		SKIPL	X,Y
05600		CAIL	X,JFNSIZE
05700		  JRST 	Z
05800		MOVEM	X,CHNL
05900		MOVE	CDB,CDBTBL(CHNL)
06000		HRRZ	X,JFNTBL(CHNL)
06100	>;LITCHN 
06200	
06300	;ONLY USES AC X
06400	DEFINE VALCH1(X,Y,Z) <
06500		SKIPL	X,Y
06600		CAIL	X,JFNSIZE
06700		   JRST	Z
06800		HRRZ	X,JFNTBL(X)
06900		JUMPE	X,Z
07000	>
07100	
07200	;TTY STUFF
07300	;FOR DEC-STYLE I/O
07400	;CHAR FOR LINE DELETION (DELLINE) AND CHARACTER DELETION (RUBCHAR)
07500	IFNDEF DELLINE,<?DELLINE←←"U"-100>	;CTRL-U	
07600	IFNDEF RUBCHAR,<?RUBCHAR←←177>		;RUBOUT
07700	IFNDEF ALTMODE,<?ALTMODE←←33	;ONE OF MANY VERSIONS>
07800	
07900	DSCR
08000		TTYINF for information about the controlling terminal.
08100	⊗
08200	
08300	?ISCTRM←← 1B0				;CHANNEL IS THE CONTROLLING TERM
08400	?TNXINP←← 0				;DO STANDARD TENEX INPUT
08500	?DECLED←← 1				;DO DEC-STYLE INPUT
08600	?TENXED←← 2				;DO TENEX-STYLE INPUT
08700	?QTTEOF←←1B17				;QUE AN EOF FOR THE TTY
     

00100	COMPIL(PAT,<OPEN,LOOKUP,ENTER,USETI,USETO,MTAPE,TENXFI,RELEASE,CLOSE,CLOSIN,CLOSO,GETCHAN,CVJFN,RENAME>
00200		,<SAVE,RESTR,RELEASE,CORGET,INSET>
00300		,<PAT -- TENEX ROUTINES EMULATING DEC CALLS>)
00400	
00500		BEGIN PAT
00600	
00700	DSCR	PROCEDURE OPEN(INTEGER CHAN; STRING DEV; INTEGER MODE,IBUF,OBUF;
00800		REFERENCE INTEGER COUNT,BR,EOF)
00900	⊗
01000	HERE(OPEN)
01100		BEGIN OPEN
01200	GTFLAGS←←4
01300	OPFLAGS←←5
01400		PUSH	P,-7(P)
01500		PUSH	P,[0]				;CLOSE INHIBIT
01600		PUSHJ	P,RELEASE			;RELEASE IF ALREADY OPEN
01700	
01800	;SEE WHAT KIND OF DEVICE WE HAVE
01900	
02000		PUSH	SP,-1(SP)
02100		PUSH	SP,-1(SP)
02200		PUSH	P,[0]
02300		PUSHJ	P,CATCHR		;PUT ON A NULL CHAR
02400		PUSHJ	P,MAKUP			;MAKE UPPER CASE (DAMMIT)
02500		PUSH	SP,-3(SP)
02600		PUSH	SP,-3(SP)
02700		PUSH	SP,[3]
02800		PUSH	SP,[POINT 7,[ASCIZ/:
02900	/]]
03000		PUSHJ	P,CAT			;PUT ON A STRING
03100		POP	SP,-4(SP)
03200		POP	SP,-4(SP)		;SAVE ABOVE
03300	
03400		PUSHJ	P,SAVE			;NOW SAVE ACS
03500		SETZ	LPSA,			;NO PARAMETERS TO REMOVE
03600		MOVE	CHNL,-7(P)			;USER CHANNEL NUMBER
03700		MOVE	1,(SP)			;STRING FOR DEVICE	
03800		SUB	SP,X22			;ADJUST STACK
03900		JSYS STDEV
04000		   JRST BADOPN			;NOT A PLAUSIBLE DEVICE
04100		PUSH	P,2			;SAVE DEVICE DESIGNATOR
04200	;ITS A PLAUSIBLE DEVICE
04300		MOVEI	C,IOTLEN
04400		PUSHJ	P,CORGET
04500		  ERR <OPEN:  CANNOT GET CORE>
04600		MOVE	CDB,B			;IO BLOCK ADDRESS
04700		MOVEM	CDB,CDBTBL(CHNL)	;SAVE 
04800	;ZERO OUT CORE (SINCE CORGET DOESNT!!!)
04900		HRL	B,B
05000		ADDI	B,1
05100		SETZM	(CDB)
05200		BLT	B,IOTLEN-1(CDB)		
05300	
05400		POP	P,1			;GET DEVICE DESIGNATOR
05500		MOVEM	1,DVDSG(CDB)		;AND SAVE IT
05600		JSYS DVCHR
05700		MOVEM	2,DVCH(CDB)		;SAVE DEVICE CHARACTERISTICS
05800		HLRZ	1,2			
05900		ANDI	1,777			;DEVICE TYPE
06000		MOVEM	1,DVTYP(CDB)		;SAVE IT
06100		MOVEI	2,STARTPAGE(CHNL)	;PAGE BUFFERING
06200		HRLI	2,400000		;XWD FORK,PAGE
06300		MOVEM	2,FKPAGE(CDB)
06400		LSH	2,9			;ADDRESS
06500		MOVEM	2,IOADDR(CDB)
06600		SETOM	IOPAGE(CDB)		;AT (MYTHICAL) PAGE -1
06700		MOVE	2,DVCH(CDB)		;DEVICE CHARS
06800		TLNN	2,100000		;IS DEVICE A DIRECTORY DEVICE	
06900		   JRST	GTNOW			;NOPE, DO GTJFN AND OPENF NO
07000	HASDIR:
07100	;GET THE MODE IN 4
07200		MOVE	4,-6(P)			;MODE
07300		ANDI	4,17			;FORGET OTHER JUNK
07400	;IF DEVICE IS A DECTAPE IN DUMP MODE THEN DO IT NOW ALSO
07500		CAIE	1,3			;IS IT A DECTAPE?
07600		  JRST	HASDI1			;NO	
07700		CAIN	4,17			;IN DUMP MODE?		
07800		  JRST	DOMNT			;YES MOUNT AND THEN OPEN
07900	;SO DONT DO GTJFN NOW, BUT WAIT
08000	HASDI1:	SETZM	JFNTBL(CHNL)		;BE SURE
08100		MOVEM	4,GFL(CDB)		;SAVE THE MODE AS THE GTJFN FLAGS
08200		HRL	4,-5(P)			;INPUT BUFFERS
08300		HRR	4,-4(P)			;OUTPUT BUFFERS	
08400		MOVEM	4,OFL(CDB)		;SAVE AS THE OPENF FLAGS
08500		JRST	GUDRET			;AND RETURN
08600	
08700	;MOUNT AND OPEN DECTAPE IN DUMP MODE
08800	DOMNT:	MOVE	A,DVDSG(CDB)		;GET DEVICE DESIGNATOR
08900		TLO	A,(1B3)			;DONT READ DIRECTORY FOR DUMP MODE
09000		JSYS MOUNT
09100		   JRST	BADOPN			;CANNOT MOUNT
09200		MOVSI	GTFLAGS,100001
09300		MOVE	1,GTFLAGS
09400		MOVE	2,(SP)
09500		JSYS GTJFN
09600		   JRST	BADOPN
09700		MOVEM	1,JFNTBL(CHNL)
09800		MOVEM	GTFLAGS,GFL(CDB)
09900		MOVE	OPFLAGS,[447400000000!RDBIT!WRBIT]
10000		MOVE	2,OPFLAGS
10100		JSYS OPENF
10200		   JRST	CNTOPN
10300		JRST	OPOK
10400	
10500	GTNOW:	
10600		MOVSI	GTFLAGS,100001
10700		MOVE	1,GTFLAGS
10800		MOVE	2,(SP)			;DEVICE STRING
10900		JSYS GTJFN	
11000		   JRST	BADOPN			;NOPE CANNOT GET
11100		MOVEM	1,JFNTBL(CHNL)		;SAVE JFN
11200		MOVEM	GTFLAGS,GFL(CDB)	;AND SAVE THEM
11300	;CHECK IF IT IS THE CONTROLLING TERMINAL (DEVICE "TTY" ONLY )
11400		MOVE	2,DVTYP(CDB)		;GET DEVICE TYPE
11500		CAIE	2,12			;IS IT A TERMINAL?
11600		  JRST	NOTTTY			;NO
11700		PUSH	P,3
11800		PUSH	P,4
11900		PUSH	P,5
12000		PUSH	P,6
12100		HRRZ	2,JFNTBL(CHNL)
12200		HRROI	1,4			;WRITE IN 4
12300		MOVSI	3,200000		;DEVICE ONLY
12400		SETZ	4,
12500		JSYS	JFNS			;GET STRING
12600		MOVEM	4,2			;SAVE IN 2
12700		POP	P,6
12800		POP	P,5			;RESTORE
12900		POP	P,4
13000		POP	P,3
13100		CAME	2,[ASCIZ/TTY/]		;DEVICE TTY?
13200		  JRST	NOTTTY			;NO
13300		MOVE	2,[ISCTRM+DECLED]	;THE CONTROLLING TERMINAL
13400		MOVEM	2,TTYINF(CDB)		;REMEMBER
13500	NOTTTY:
13600	;COMPUTE OPENF FLAGS
13700		SETZ	OPFLAGS,
13800		MOVE	2,DVCH(CDB)		;DEVICE CHARACTERISTICS
13900		TESTE	2,<1B1>			;CAN DO INPUT?
14000		   TESTO  OPFLAGS,RDBIT
14100		TESTE	2,<1B0>			;CAN DO OUTPUT?
14200		   TESTO  OPFLAGS,WRBIT
14300		MOVE	1,DVTYP(CDB)		;CHECK DEVICE TYPE
14400		CAIE	1,7			;IS IT THE LPT?
14500		CAIN	1,12			;IS IT A TTY?
14600		   JRST	OP7BT			;USE 7 BIT BYTES
14700	;NOW TRY VARIOUS THINGS, LOOKING FOR SOMETHING THAT WORKS
14800	
14900		HRRZ	1,JFNTBL(CHNL)
15000		HRLI	OPFLAGS,440000
15100		MOVE	2,OPFLAGS		;36-BIT, MODE 0
15200		JSYS OPENF	
15300		   SKIPA
15400		JRST	OPOK	
15500		HRRZ	1,JFNTBL(CHNL)
15600		HRLI	OPFLAGS,447400		;36-BIT, MODE 17
15700		MOVE	2,OPFLAGS
15800		JSYS OPENF
15900		  SKIPA
16000		JRST 	OPOK
16100	OP7BT:	HRRZ	1,JFNTBL(CHNL)
16200		HRLI	OPFLAGS,70000		;7-BIT, MODE 0
16300		MOVE	2,OPFLAGS
16400		JSYS OPENF
16500		   JRST NOOPN
16600	OPOK:	MOVEM	OPFLAGS,OFL(CDB)	;SAVE OP FLAGS
16700	GUDRET:	
16800	;SAVE FLAGS
16900		SETOM	OPNDUN(CDB)		;INDICATE OPENED WITH OPEN
17000		POP	P,TEMP			;RETURN ADDRESS
17100		POP	P,ENDFL(CDB)		;SAVE GOOD THINGS
17200		POP	P,BRCHAR(CDB)
17300		POP	P,ICOUNT(CDB)		
17400		SETZM	@ENDFL(CDB)		;INDICATE GOOD OPENING
17500		SUB	SP,X22			;CLEAN UP STACKS
17600		SUB	P,X44
17700		JRST	RESTR			;AND RETURN
17800		
17900	
18000	NOOPN:
18100	CNTOPN:	SKIPN	1,JFNTBL(CHNL)		;RELEASE JFN
18200		JSYS RLJFN
18300		  JFCL
18400	BADOPN:
18500		SKIPE	B,CDBTBL(CHNL)		;CORE ALLOCATED?
18600		  PUSHJ	P,CORREL		;RELEASE CORE
18700		SETZM	JFNTBL(CHNL)
18800		SETZM	CDBTBL(CHNL)
18900		SKIPN	@-1(P)			;USER WANTS ERROR?
19000		  ERR	<OPEN:  IO ERROR OR ILLEGAL SPECIFICATIONS>,1
19100		SETOM	@-1(P)
19200		POP	P,TEMP
19300		SUB	P,[XWD 7,7]
19400		SUB	SP,X22	
19500		JRST	RESTR
19600	
19700	
19800	
19900	
20000		BEND OPEN
20100	
20200	;MAKE UPPER CASE LETTERS
20300	MAKUP:	PUSHJ	P,SAVE
20400		SKIPE	SGLIGN(USER)
20500		  PUSHJ	P,INSET
20600		HRRZ	A,-1(SP)		;LENGTH OF STRING	
20700		ADDM	A,REMCHR(USER)
20800		SKIPLE	REMCHR(USER)		;OK?
20900		  PUSHJ	P,STRNGC		;NO, COLLECT
21000		MOVE	B,A
21100		HRRO	A,A
21200		PUSH	SP,A
21300		PUSH	SP,TOPBYTE(USER)
21400	UPPER1:	JUMPLE	B,UPPER2		;DONE YET?
21500		ILDB	C,-2(SP)		;NEXT CHAR
21600		CAIL	C,141		
21700		CAILE	C,172
21800		  SKIPA	
21900		SUBI	C,40			;CONVERT TO UPPER CASE
22000		IDPB	C,TOPBYTE(USER)
22100		SOJA	B,UPPER1	
22200	UPPER2:	POP	SP,-2(SP)
22300		POP	SP,-2(SP)
22400		SETZ	LPSA,
22500		POP	P,TEMP			;RETURN ADDR
22600		JRST	RESTR			;RETURN
22700	
     

00100	DSCR  PROCEDURE LOOKUP(INTEGER CHNL; STRING FILE; REFERENCE INTEGER FLAG)
00200	
00300	⊗
00400	
00500	HERE(LOOKUP)
00600		BEGIN	LOOKUP
00700		PUSHJ	P,TENXFI		;MAKE THE FILE SPEC TENEX
00800	
00900		PUSH	P,1
01000		PUSH	P,2
01100		PUSH	P,3
01200		PUSH	P,CHNL
01300		PUSH	P,CDB
01400		DEFINE CHNARG <-7(P)>
01500		DEFINE FLGARG <-6(P)>
01600	
01700		SETZM	@FLGARG			;CLEAR FLAG
01800		SKIPL	CHNL,CHNARG
01900		CAIL	CHNL,JFNSIZE	
02000		   JRST	BADLU1
02100		MOVE	CDB,CDBTBL(CHNL)
02200		SKIPN	OPNDUN(CDB)		;ERROR IF NOT OPENED
02300		   JRST	BADLU1
02400		MOVE	2,DVCH(CDB)		;GET DEVICE CHARACTERISTICS
02500		TLNN	2,100000		;DOES DEVICE HAVE A DIRECTORY?
02600		   JRST	LUKRET			;NO, NO LOOKUP
02700		SKIPE	JFNTBL(CHNL)		;JFN ALREADY ASSIGNED?
02800		   PUSHJ P,RELNOW		;YES, RELEASE IT
02900	
03000		PUSHJ	P,DEVCAT
03100	
03200		MOVSI	1,100001		;OLD FILE
03300		MOVE	2,(SP)
03400		JSYS GTJFN	
03500		   JRST	BADLUK
03600		MOVEM	1,JFNTBL(CHNL)
03700		MOVSI	3,100001
03800		MOVEM	3,GFL(CDB)
03900		MOVE	2,[XWD 440000,200000]	;36-BIT
04000		JSYS OPENF
04100		   SKIPA
04200		JRST 	GUDLUK
04300		MOVE	1,JFNTBL(CHNL)
04400		MOVE	2,[XWD 447400,200000]	;36-BIT, DUMP
04500		JSYS OPENF
04600		   SKIPA
04700		JRST	GUDLUK
04800		MOVE	1,JFNTBL(CHNL)
04900		MOVE	2,[XWD 70000,200000]	;7-BIT
05000		JSYS OPENF
05100		   JRST	BADLUK
05200	GUDLUK:	MOVEM	2,OFL(CDB)
05300		SETZM	@FLGARG
05400	LUKRET:	POP	P,CDB
05500		POP	P,CHNL
05600		POP	P,3
05700		POP	P,2
05800		POP	P,1
05900		SUB	SP,X22
06000		SUB	P,X33
06100		JRST	@3(P)
06200	
06300	BADLUK:	MOVEM	1,@FLGARG
06400		JRST	LUKRET
06500	
06600	BADLU1:	SETOM	@FLGARG		
06700		JRST	LUKRET
06800	
06900	
07000		BEND LOOKUP
07100	
07200	DEVCAT:
07300	;HERE WITH CDB LOADED, FILENAME ON THE SP STACK
07400	;RETURN WITH "DEV:FILE" & 0 ON THE SP STACK
07500	;MUST NOT HAVE CALLED SAVE WHEN THIS IS CALLED
07600		PUSH	P,1
07700		PUSH	P,2
07800		PUSH	P,[=100]
07900		PUSHJ	P,ZSETST		;BP IN 1
08000		MOVE	2,DVDSG(CDB)		;DEVICE DESIGNATOR
08100		JSYS	DEVST
08200		   ERR <LOOKUP, ENTER, OR RENAME:  CANNOT DO DEVST>
08300		PUSH	P,[=100]
08400		PUSH	P,1			;UPDATED BP
08500		PUSHJ	P,ZADJST
08600		PUSH	P,[":"]
08700		PUSHJ	P,CATCHR
08800		PUSHJ	P,CAT.RV		
08900		PUSH	P,[0]
09000		PUSHJ	P,CATCHR
09100		POP	P,2
09200		POP	P,1
09300		POPJ	P,
09400	
09500	;RELEASE JFN ALREADY THERE
09600	RELNOW:	
09700		PUSH	P,CHNL			;CHANNEL
09800		PUSHJ	P,CLOSF			;CLOSE DANCE
09900		PUSH	P,1
10000		MOVE	1,JFNTBL(CHNL)		;GET JFN	
10100		JSYS	RLJFN			;RELEASE
10200		  ERR <CANNOT RELEASE JFN>,1
10300		SETZM	JFNTBL(CHNL)		;AND ZERO OUT
10400		SETZM	IOSTT(CDB)		;NO STATUS
10500		POP	P,1
10600		POPJ	P,
10700	
10800		
     

00100	HERE(ENTER)
00200		BEGIN ENTER
00300	
00400		PUSHJ	P,TENXFI
00500	
00600		PUSH	P,1
00700		PUSH	P,2
00800		PUSH	P,3
00900		PUSH	P,CHNL
01000		PUSH	P,CDB
01100		DEFINE 	CHNARG <-7(P)>
01200		DEFINE	FLGARG <-6(P)>
01300	
01400		SETZM	@FLGARG			;CLEAR FLAG FOR USER
01500		SKIPL	CHNL,CHNARG
01600		CAIL	CHNL,JFNSIZE
01700		   JRST	BADEN1
01800		MOVE	CDB,CDBTBL(CHNL)
01900		SKIPN	OPNDUN(CDB)
02000		   JRST	BADEN1			;WAS AN OPEN PERFORMED HERE?
02100		SKIPN	1,JFNTBL(CHNL)
02200		   JRST	NOTOPN
02300		MOVE	2,DVCH(CDB)		;GET DEVICE CHARACTERISTICS
02400		TLNN	2,100000		;DOES DEVICE HAVE DIRECTORY?
02500		   JRST	ENTRET			;NO
02600	
02700		SKIPGE	IOSTT(CDB)		;A DEC-STYLE CLOSE DONE? CHKDECCLZ
02800		  JRST [PUSHJ P,RELNOW		;RELEASE JFN
02900			JRST NOTOPN		;AND PROCEED
03000		      ]
03100	
03200		PUSH	P,1			;SAVE JFN
03300		SETO	1,			;UNMAP THE BUFFER PAGE
03400		MOVE	2,FKPAGE(CDB)
03500		SETZ	3,
03600		JSYS	PMAP			;REMOVE PAGE
03700		POP	P,1
03800	
03900		SETOM	IOPAGE(CDB)
04000		SETZM	IOSTT(CDB)
04100		
04200		PUSH	P,1			;SAVE JFN
04300		TLO	1,400000		;DO NOT RELEASE THE JFN
04400		JSYS 	CLOSF
04500		   JFCL	;IGNORE
04600		POP	P,1
04700		MOVE	2,OFL(CDB)
04800		TESTO	2,WRBIT			;TURN ON WRITE BIT
04900		MOVEM	2,OFL(CDB)		;AND SAVE NEW FLAGS
05000		JSYS OPENF
05100		   JRST	BADENT			;ERROR IN 1	    
05200		JRST	ENTRET			;RETURN
05300	
05400	NOTOPN:	
05500		PUSHJ	P,DEVCAT
05600	
05700		MOVSI	1,600001		;NEW FILE
05800		MOVE	2,(SP)
05900		JSYS GTJFN
06000		   JRST	BADENT			;CANNOT GTJFN
06100		MOVEM	1,JFNTBL(CHNL)
06200		MOVSI	2,600001		;THE 
06300		MOVEM	2,GFL(CDB)		;SAVE THE GTJFN FLAGS
06400	B36:	HRRZ	1,JFNTBL(CHNL)
06500		MOVE	2,[XWD 440000,100000]	;36-BIT
06600		JSYS OPENF	
06700		   SKIPA
06800		JRST	ENT1	
06900		HRRZ	1,JFNTBL(CHNL)
07000		MOVE	2,[XWD 447400,100000]	;36-BIT, DUMP
07100		JSYS OPENF
07200		   SKIPA
07300		JRST	ENT1
07400		HRRZ	1,JFNTBL(CHNL)
07500		MOVE	2,[XWD 70000,100000]
07600		JSYS OPENF
07700		   JRST	BADENT
07800	ENT1:	MOVEM	2,OFL(CDB)
07900	ENTRET:	SETZM	@FLGARG
08000	ENTPOP:	POP	P,CDB
08100		POP	P,CHNL
08200		POP	P,3
08300		POP	P,2
08400		POP	P,1
08500		SUB	SP,X22
08600		SUB	P,X33
08700		JRST	@3(P)
08800	
08900	
09000	BADENT:	MOVEM	1,@FLGARG
09100		JRST	ENTPOP
09200	
09300	BADEN1:	SETOM	@FLGARG
09400		JRST	ENTPOP
09500	
09600		BEND ENTER
09700		
     

00100	DSCR
00200		RENAME(CHNL,"STR",PROT,@FLAG)
00300		Since protection is not implemented in TENEX,
00400	the feature will be ignored.
00500	⊗
00600	
00700	HERE(RENAME)
00800		BEGIN RENAME
00900		PUSH	P,1
01000		PUSH	P,2
01100		PUSH	P,3
01200		PUSH	P,CHNL
01300		PUSH	P,CDB
01400		DEFINE CHNARG <-10(p)>
01500		DEFINE FLGARG <-6(P)>	
01600	
01700		VALCHN	1,CHNARG,RENBAD
01800		PUSHJ	P,OPNCHK		;MAKE SURE OPEN (SOMEWHAT REDUNDANT)
01900		MOVE	2,DVCH(CDB)		;DEVICE CHARS
02000		TLNN	2,100000		;DIRECTORY DEVICE?
02100		  JRST	RENRET			;NO, NOP
02200		
02300		PUSHJ	P,TENXFI		;MAKE A TENEX FILE NAME
02400	
02500	;PERHAPS ONLY A DELETE?
02600		HRRZ	2,-1(SP)		;NULL FILE SPEC?
02700		JUMPE	2,RENDEL		;YES, DELETE 	
02800	
02900	;ACTUALLY RENAME (ON THE SAME DEVICE)
03000		PUSH	P,CHNARG
03100		PUSHJ	P,CLOSF			;FIRST CLOSE THE FILE
03200	
03300		PUSHJ	P,DEVCAT
03400	
03500		MOVE	3,1			;SAVE FIRST JFN
03600		MOVE	1,GFL(CDB)		;USE SAME FLAGS
03700		TESTZ	1,OLDBIT		;EXCEPT NOT OLD
03800		TESTO	1,NEWBIT		;BUT DO WANT NEW
03900		TESTO	1,OUTBIT		;AND VERSION DEFAULTING
04000		MOVEM	1,GFL(CDB)		;SAVE FLAGS
04100		MOVE	2,(SP)
04200		JSYS GTJFN
04300		   JRST	RENERR			;ERROR BITS IN 1
04400		
04500		MOVE	2,1			;NEW JFN	
04600		MOVE	1,3			;OLD JFN
04700		JSYS RNAMF
04800		   JRST	RENERR			;ERROR BITS IN 1
04900		MOVE	1,2			;NEW JFN
05000		MOVE	2,OFL(CDB)		;OPENF FLAGS
05100		JSYS	OPENF
05200		   JRST	RENERR			;ERROR BITS IN 1
05300		MOVEM	1,JFNTBL(CHNL)		;SAVE THE NEW JFN
05400	
05500	RENRET:	SETZM	@FLGARG			;INDICATE A GOOD RETURN
05600	RENRE1:	POP	P,CDB
05700		POP	P,CHNL
05800		POP	P,3
05900		POP	P,2
06000		POP	P,1
06100		SUB	SP,X22
06200		SUB	P,X44
06300		JRST	@4(P)
06400	
06500	RENERR:	MOVEM	1,@FLGARG
06600		JRST	RENRE1
06700	
06800	RENBAD:	SETOM	@FLGARG
06900		JRST	RENRE1
07000	
07100	RENDEL:	TLO	1,400000		;TURN ON BIT 0 FOR NO RELEASE
07200		JSYS DELF			;JFN IN 1
07300		   JRST	RENERR
07400		JRST	RENRET
07500		BEND RENAME
07600	
     

00100	DSCR PROCEDURE USETI,USETO(INTEGER CHANNEL,BLOCK)
00200	⊗
00300	
00400	HERE(USETI)
00500	HERE(USETO)
00600		BEGIN USETS
00700	
00800		PUSH	P,1
00900		PUSH	P,2
01000		PUSH	P,3
01100		PUSH	P,CHNL
01200		SETZM	.SKIP.
01300		VALCHN	1,-6(P),USETERR
01400		MOVE	2,DVTYP(CDB)
01500		CAIN	2,3			;IS IT A DECTAPE
01600		  JRST	USEDTA
01700		MOVE	2,-5(P)			;ARGUMENT
01800		SOJ	2,
01900		LSH	2,7			;CONVERT BLOCK TO WORD NUMBER
02000		PUSH	P,-6(P)			;CHANNEL ARG
02100		PUSH	P,2			;WORD TO SET TO
02200		PUSHJ	P,SWDPTR		;SET THE WORD POINTER
02300	USETRET:POP	P,CHNL
02400		POP	P,3
02500		POP	P,2
02600		POP	P,1
02700		SUB	P,X33
02800		JRST	@3(P)
02900	
03000	
03100	USEDTA:
03200		MOVEI	2,30			;OPERATION 30 FOR DECTAPES
03300		HRRZ	3,-5(P)			;TAPE BLOCK
03400		JSYS MTOPR				;SET DIRECTLY
03500		JRST	USETRET			;AND RETURN
03600	
03700	USETER: ERR<Illegal JFN>,1
03800		SETOM	.SKIP.
03900		JRST	USETRET			;AND RETURN
04000	
04100		BEND USETS
04200			
     

00100	DSCR	PROCEDURE CLOSE(INTEGER CHANNEL,[CLOSE_INHIBIT_BITS])
00200		procedure closo(integer chan; integer bits(0))
00300		procedure closin(integer chan; integer bits(0))
00400	⊗
00500		BEGIN CLOSES
00600	
00700	HERE(CLOSIN)
00800	HERE(CLOSO)
00900		PUSH 	P,-2(P)
01000		PUSHJ	P,CLOSF
01100		PUSHJ	P,SAVE
01200		VALCHN	1,-2(P),.+2
01300		SETOM	IOSTT(CDB)		;MARK AS BEING CLOSED
01400		MOVE	LPSA,X33
01500		JRST	RESTR
01600	
01700	HERE(CLOSE)
01800	DOOPN:	PUSH	P,-2(P)
01900		PUSHJ	P,CLOSF			;FORCE BUFFERS OUT, WRITE MAGT EOFS, CLOSF
02000		PUSHJ	P,SAVE
02100		VALCHN	1,-2(P),CLORET
02200		SETOM	IOSTT(CDB)		;MARK AS BEING CLOSED
02300	CLORET:	MOVE	LPSA,X33
02400		JRST	RESTR
02500	
02600		BEND CLOSES
02700	
     

00100	HERE(RELEASE)
00200	DSCR
00300		Ignores the close inhibit bits that are available in 
00400	the STANFORD SAIL, until we decide what to do with them.
00500	⊗
00600	
00700		PUSH	P,1
00800		PUSH	P,-3(P)		;CHANNEL
00900		PUSHJ	P,CFILE
01000		POP	P,1		;RESTORE 1
01100		SUB	P,X33
01200		JRST	@3(P)		;RETURN
01300	
01400	
01500	
01600	
     

00100	DSCR	
00200		PROCEDURE MTAPE(INTEGER CHAN,OPERATION)
00300	(the operation is a character e.g., "U" to unload)
00400	as in the SAIL manual.
00500	⊗
00600	
00700	HERE(MTAPE)
00800		BEGIN MTAPE
00900		PUSHJ	P,SAVE
01000		MOVE	LPSA,X33
01100		LDB	C,[POINT 5,-1(P),35]
01200		MOVE	A,OPTAB
01300		MOVE	B,OPTAB+1
01400		TRZE	C,30			;COMPRESS TABLE
01500		ADDI	C,5	
01600		LSH	C,2
01700		ROTC	A,(C)
01800		ANDI	B,17
01900		VALCHN	1,-2(P),MTAERR
02000		PUSHJ	P,OPNCHK		;MAKE SURE OPEN
02100		JSYS MTOPR
02200		JRST	RESTR
02300	MTAERR: ERR <Illegal JFN>,1
02400		JRST	RESTR
02500	
02600	OPTAB:	BYTE (4) 16,17,0,0,3,6,7,13,10	;A,B,E,F,R,S,T
02700		BYTE (4) 11,0,1			;U,W
02800	
02900		BEND MTAPE
03000	
03100		
03200	
03300	
     

00100	DSCR	STRING PROCEDURE TENXFI(STRING DECFILE)
00200	
00300		Converts the string to a TENEX file specification.
00400	A la Alex Cannara.
00500	⊗
00600	
00700	HERE(TENXFI)
00800		BEGIN TENXFI
00900	
01000	CTRLV←←"V"-100
01100	FIND←←2
01200	
01300		PUSH	P,1
01400		PUSH	P,2
01500		PUSH	P,3
01600		SETZM	FIND
01700		PUSH	SP,[0]		;DEVICE TEMPORARY
01800		PUSH	SP,[0]
01900		PUSH	SP,[0]		;DIR TEMPORARY
02000		PUSH	SP,[0]
02100		PUSH	SP,[0]		;NAM TEMPORARY
02200		PUSH	SP,[0]	
02300	
02400	DEFINE ORIG <-7(SP)>
02500	DEFINE ORIG1 <-6(SP)>
02600	DEFINE DEV <-5(SP)>
02700	DEFINE DEV1 <-4(SP)>
02800	DEFINE DIR <-3(SP)>
02900	DEFINE DIR1 <-2(SP)>
03000	DEFINE NAM <-1(SP)>
03100	DEFINE NAM1 <0(SP)>
03200	
03300	;SIMPLE SINCE NAME IS AT THE TOP OF SP
03400	DEFINE CATNAM (X) <
03500		PUSH	P,X
03600		PUSHJ	P,CATCHR
03700	>
03800	DEFINE CATDIR (X) <
03900		PUSH	P,X
04000		PUSH	SP,DIR
04100		PUSH	SP,DIR
04200		PUSHJ	P,CATCHR
04300		POP	SP,-4(SP)
04400		POP	SP,-4(SP)
04500	>
04600	
04700	DEFINE GCH <
04800		HRRZ	1,ORIG
04900		JUMPE	1,TENDUN
05000		ILDB	3,ORIG1
05100		SOS	ORIG
05200	>
05300	
05400	
05500	TENX1:	GCH
05600		CAIE	3,CTRLV
05700		  JRST	NOQUOTE
05800		SKIPE	FIND
05900		  JRST	QUODIR
06000		PUSHJ	P,CATNA3
06100		GCH	
06200		PUSHJ	P,CATNA3 		;AND THE CHAR FOLLOWING THE CTRLV	
06300		JRST	TENX1
06400	QUODIR:	PUSHJ	P,CATDI3
06500		GCH
06600		PUSHJ	P,CATDI3
06700		JRST	TENX1			;AND CONTINUE
06800	
06900	NOQUOTE:
07000		CAIN	3,":"			;COLON -- DEVICE
07100		   JRST	ISDEV			;ITS BEEN A DEVICE ALL ALONG!!
07200		CAIN	3,","
07300		   JRST	TENX1			;IGNORE COMMA
07400		CAIE	3,40			;SPACE
07500		CAIN	3,11			;OR TAB
07600		   JRST	TENX1
07700	
07800		CAIE	3,"<"			;THESE START THE DIRECTORY NAME
07900		CAIN	3,"["
08000		   JRST	STDIR
08100		CAIE	3,">"			;THESE FINISH THE DIR. NAME
08200		CAIN	3,"]"
08300		   JRST	ENDDIR
08400		SKIPE	FIND			;DOING DIRECTORY?
08500		   JRST	.+3			;YES
08600		PUSHJ	P,CATNA3
08700		JRST	TENX1
08800		PUSHJ	P,CATDI3
08900		JRST	TENX1
09000	
09100	STDIR:	SETOM	FIND
09200		SKIPE	DIR			;ANYTHING THERE?
09300		   JRST	TENX1			;YES, IGNORE
09400		CATDIR	<[74]>
09500		JRST	TENX1
09600	
09700	ENDDIR:	SETZM	FIND
09800		JRST	TENX1
09900	
10000	ISDEV:	PUSHJ	P,CATNA3		;PUT THE COLON ON THE NAME
10100		MOVE	3,NAM			;THE "NAME" HAS REALLY BEEN A DEV
10200		MOVEM	3,DEV
10300		MOVE	3,NAM1
10400		MOVEM	3,DEV1			
10500		
10600		SETZM	NAM			;SO CLEAR THE NAME -- START OVER
10700		SETZM	NAM1
10800		JRST	TENX1
10900	
11000	TENDUN:	
11100	;CHECK TO SEE WHAT LAST CHAR OF DIR IS
11200		SKIPN	DIR
11300		  JRST	GOTDIR			;NO DIRECTORY THERE
11400		CATDIR	<[76]>			;PUT ON A ">"
11500	;NOW STACK HAS ORIG,DEV,DIR,NAM
11600	GOTDIR: 
11700		PUSHJ	P,CAT
11800	;NOW STACK HAS ORIG,DEV,<DIR>NAM
11900		PUSHJ	P,CAT
12000	;NOW STACK HAS ORIG,DEV:<DIR>NAM
12100	GOTDI1:	POP	SP,-2(SP)
12200		POP	SP,-2(SP)
12300	
12400	TXFRET:
12500		POP	P,3
12600		POP	P,2
12700		POP	P,1
12800		POPJ	P,
12900	
13000	
13100	;CALL CAT MACROS WITH AC 3 AS THE ARG
13200	CATNA3:	CATNAM 3
13300		POPJ	P,
13400	
13500	CATDI3:	CATDIR 3
13600		POPJ	P,
13700	
13800	
13900		BEND TENXFI
14000	
     

00100	DSCR
00200		INTEGER PROCEDURE GETCHAN(INTEGER I)
00300	RETURNS AN UNUSED CHANNEL NUMBER, AND MARKS IT
00400	FOR USE, SO THAT NO ONE WILL TRY TO USE IT.
00500	⊗
00600	
00700	HERE(GETCHAN)
00800		MOVE	A,[XWD -JFNSIZE+1,1]		;START AT CHANNEL 1
00900	GETCH1:	SKIPN	CDBTBL(A)	;ALLOCATED YET?
01000		   JRST	GETCH2		;NO, TAKE IT
01100		AOBJN A,GETCH1	;YES
01200		SETOM	A		;INDICATE ERROR 
01300		POPJ	P,
01400	
01500	GETCH2:	HRRZ	A,A
01600		PUSH	P,B		;NOW ALLOCATE A TABLE
01700		PUSH	P,C
01800		MOVEI	C,IOTLEN
01900		PUSHJ	P,CORGET
02000		  ERR <GETCHAN:  CANNOT GET CORE>
02100		MOVEM	B,CDBTBL(A)
02200	
02300		HRL	C,B		;ZERO OUT BLOCK
02400		HRRI	C,1(B)
02500		SETZM	(B)
02600		BLT	C,IOTLEN-1(B)
02700			
02800		SETZM	JFNTBL(A)	;BUT NO JFN (YET)
02900		POP	P,C
03000		POP	P,B
03100		POPJ	P,
03200	
03300	DSCR
03400		INTEGER PROCEDURE CVJFN(INTEGER CHAN)
03500	
03600		Returns the JFN (XWD flags,jfn)  associated
03700	with a logical channel, -1 if no jfn assigned.
03800		Hereby, the user of these routines can access
03900	the system directly if the need arises.
04000	⊗
04100	HERE(CVJFN)
04200		SKIPL	1,-1(P)
04300		CAIL	1,JFNSIZE
04400		  JRST 	CVJFER
04500		SKIPN	1,JFNTBL(1)
04600		  JRST	CVJFER
04700	CVJFR:	SUB	P,X22
04800		JRST	@2(P)
04900	CVJFER:	SETO	1,
05000		JRST	CVJFR
05100	
05200	
05300	BEND PAT
05400	
05500	ENDCOM(PAT)
05600	
     

00100	COMPIL(JOBINF,<ODTIM,IDTIM,RUNTM,GTAD,GJINF>,<ZSETST,ZADJST,X22,X33,X44,.SKIP.,CATCHR>
00200		,<JOBINF -- JOB UTILITY ROUTINES>)
00300	DSCR STRING SIMPLE PROCEDURE ODTIM(INTEGER DT,FORMAT)
00400		Returns the string representation of DT
00500	(which is in internal TENEX representation).  If DT
00600	is -1 the current date and time are used.  If format
00700	is -1, the standard format is used.
00800	⊗
00900	HERE(ODTIM)
01000		PUSH	P,[=100]	; 100 CHARS
01100		PUSHJ	P,ZSETST	;GET BP IN 1
01200		MOVE 2,-2(P)		;TIME
01300		MOVE 3,-1(P)		;FORMAT
01400		JSYS ODTIM
01500		PUSH	P,[=100]
01600		PUSH	P,1		;UPDATED BP
01700		PUSHJ	P,ZADJST	;GET STRING
01800		SUB	P,X33		;ADJUST STACK
01900		JRST	@3(P)		;RETURN
     

00100	
00200	DSCR INTEGER SIMPLE PROCEDURE IDTIM(STRING S)
00300		Returns the internal TENEX representation of S, which
00400	is assumed to be the date and time in some reasonable format.
00500	If the format cannot be scanned, the error is returned in .SKIP.
00600	
00700	⊗
00800	
00900	HERE(IDTIM)
01000		PUSH	P,[0]
01100		PUSHJ	P,CATCHR		
01200		MOVE 	1,(SP)			;BYTE-POINTER
01300		SETZB 	2,.SKIP.		;NO SPECIAL FORMAT, ASSUME NO ERROR
01400		JSYS IDTIM
01500		  MOVEM 2,.SKIP.		;ERROR TO USER
01600		MOVE  	1,2			;ANSWER
01700		SUB	SP,X22			;ADJUST SP STACK
01800		POPJ	P,			;RETURN
     

00100	DSCR INTEGER SIMPLE PROCEDURE RUNTM(INTEGER FORK; REFERENCE INTEGER CONSOLE);
00200		Returns the runtime of a fork.  If FORK=-5, then then
00300	whole job.  Time is returned as milliseconds for you.  Console time,
00400	similarly converted, is returned in CONSOLE.
00500	⊗
00600	HERE(RUNTM)
00700		MOVE 	1,-2(P)
00800		JSYS RUNTM
00900		MOVEM 	3,@-1(P)
01000		SUB	P,X33	
01100		JRST	@3(P)
     

00100	DSCR INTEGER SIMPLE PROCEDURE GTAD;
00200		Returns the current date and time.  See Jsys manual,
00300	3-3.
00400	⊗
00500	HERE(GTAD)
00600		JSYS GTAD
00700		POPJ P,
     

00100	DSCR INTEGER SIMPLE PROCEDURE GJINF(REFERENCE INTEGER LOGDIR,CONDIR,TTYNO);
00200		Returns the TENEX jobnumber.  LOGDIR is the directory 
00300	no. logged in, CONDIR is the connected directory number.  TTYNO is the
00400	TENEX teletype number, which is -1 if the job is detached.  
00500		See the DIRST routine for converting directory numbers to 
00600	directory strings.
00700	⊗
00800	
00900	HERE(GJINF)
01000		JSYS GJINF
01100		MOVEM 	1,@-3(P)
01200		MOVEM 	2,@-2(P)
01300		MOVEM 	4,@-1(P)
01400		MOVE 	1,3;
01500		SUB	P,X44
01600		JRST	@4(P)
     

00100	ENDCOM(JOBINF)
00200	
     

00100	COMPIL(DIRECT,<STDIR,DIRST>,<X22,X33,CATCHR,ZSETST,ZADJST.SKIP.>
00200		,<DIRECT -- TENEX DIRECTORY SPECS>)
00300	DSCR INTEGER SIMPLE PROCEDURE STDIR(STRING S; BOOLEAN DORECOGNITION)
00400	DESR
00500		Returns the directory number associated with a string.
00600	Any problems are returned in .SKIP. with the code:
00700			1 string does not match
00800			2 string is ambiguous.
00900	⊗
01000	HERE(STDIR)
01100		PUSH	P,[0]
01200		PUSHJ	P,CATCHR	;TACK ON 0
01300		SETZ 	3,		;
01400		MOVEI 	1,1 		; ASSUME NO RECOGNITION
01500		SKIPE 	-1(P)		; DO WE WANT IT?
01600		SETO  	1,		; YES AFTER ALL
01700		MOVE 	2,(SP)		;BYTE-POINTER
01800		JSYS STDIR
01900		  SKIPA	3,[1]		; NO MATCH;
02000		  MOVEI	3,2 		; AMBIGUOUS
02100		MOVEM 	3,.SKIP.	; SAVE IT FOR USER
02200		HRRZ 	1,1 		; SAVE DIR NO. (ONLY)
02300		SUB	SP,X22		;ADJUST STRING STACK
02400		SUB	P,X22
02500		JRST	@2(P)		;RETURN	
02600		
     

00100	DSCR STRING SIMPLE PROCEDURE DIRST(INTEGER I)
00200		Returns the string name for directory I.  Any problems
00300	cause .SKIP. to be set TRUE.
00400	⊗
00500	
00600	HERE(DIRST)
00700		BEGIN 	DIRST
00800		PUSH	P,[=100]
00900		PUSHJ	P,ZSETST
01000		SETZM 	.SKIP.
01100		MOVE 	2,-1(P)		;DIRECTORY NO.
01200		PUSH	P,1		;SAVE STRING POINTER
01300		JSYS DIRST
01400		  JRST	DIRERR		;ERROR RETURN
01500		SUB	P,X11		;CLEAR STACK, DONT NEED STRING POINTER
01600	DOADJ:	PUSH	P,[=100]
01700		PUSH	P,1		;UPDATED STRING POINTER
01800		PUSHJ	P,ZADJST	;GET SAIL STRING ON STACK
01900		SUB	P,X22		
02000		JRST	@2(P)
02100	
02200	DIRERR:	MOVEM	1,.SKIP.	;ERROR NUMBER IN TOPS 20, STRING POINTER IN TENEX
02300					;ALWAYS TRUE
02400		POP	P,1		;GET BACK ORIGINAL BP
02500		JRST	DOADJ		;AND FIX STRINGS
02600		BEND 	DIRST
02700	ENDCOM(DIRECT)
     

00100	COMPIL(RUNPRG,<RUNPRG>,<X22,X33,CATCHR>,<RUNPRG -- RUN A PROGRAM>)
00200	DSCR INTEGER SIMPLE PROCEDURE RUNPRG(STRING PROGRAM; INTEGER INCREM; BOOLEAN NEWFORK)
00300		This does two entirely different things depending on whether
00400	NEWFORK is true or not.
00500		If NEWFORK then a new fork is created, capabilities transmitted,
00600	and PROGRAM is run there.  INCREM is added to the entry vector.  Any problems
00700	cause the routine to return FALSE, otherwise it returns TRUE.
00800		If not NEWFORK then the current job is destroyed and replaced
00900	with PROGRAM, with INCREM added to the entry vector location.  This is
01000	like the DEC RUN uuo, and hence if the increment is 1, the program is
01100	started at the CCL address.  If the routine returns at all, there was a problem
01200	with the file.
01300		Remember to say .SAV as the PROGRAM extension.
01400	⊗
01500	
01600	
01700	HERE(RUNPRG)
01800		BEGIN 
01900		JFN←←0
02000		FORK←←14
02100		PUSH	P,[0]
02200		PUSHJ	P,CATCHR	
02300		MOVSI	1,100001 	; OLD FILE, PTR IN 2	
02400		MOVE	2,(SP) 		; STRING POINTER
02500		JSYS GTJFN 			; TRY FOR JFN		
02600		   JRST RUNERR 		; ERROR
02700		MOVEM	1,JFN 		; SAVE JFN		
02800	
02900		SKIPN	-1(P) 		; USER WANTS FORK?
03000		   JRST SWP 		; NO, REPLACE CURRENT PRG
03100	
03200		MOVSI	1,100000 	; XMIT CAPABILITIES
03300		JSYS CFORK
03400		   JRST RUNERR 	; CANNOT CREATE FORK
03500		MOVEM	1,FORK 	; SAVE HANDLE
03600		SETOB	2,3 	; INDICATE ALL PRIVILEDGES
03700		JSYS EPCAP
03800		HRLZ	1,1 	; FORK HANDLE
03900		HRR	1,JFN 	; THE JFN
04000		JSYS GET 		; JSYS GET THE FILE
04100		MOVEI	1,400000 	; CURRENT FORK
04200		JSYS	GPJFN	;PRIMARY JFNS IN 2
04300		MOVE	1,FORK 	; SET PRIMARY IO	
04400		JSYS SPJFN	;FOR NEW FORK
04500		MOVE	1,FORK 	; FORK
04600		MOVE	2,-2(P) 	; USER VALUE FOR ENTRY VECTOR
04700		JSYS SFRKV	;START THE FORK
04800		MOVE	1,FORK ;
04900		JSYS WFORK
05000		SKIPE	1,FORK 	; SET TO KILL
05100		JSYS KFORK	;KILL THE FORK
05200		HRRZ	1,JFN ;
05300		JSYS RLJFN 		; RELEASE
05400		JFCL 		; IGNORE	
05500		JRST 	RUNRET 		; AND RETURN SAFELY
05600	
05700	SWP:	
05800	IMSSS,<				;DESTROY EMULATOR INFO AT IMSSS
05900		SETO	1,
06000		MOVE	2,[XWD 400000,711]	;PAGE 711
06100		JSYS	PMAP			;DESTROY
06200	>;IMSSS
06300		PUSH	P,JFN			;SAVE THE JFN
06400		HRLI	A1 			; BLT INTO ACS
06500		HRRI	1 ;
06600		BLT	15 		; THE INSTRUCTIONS -- NOTE THAT RF IS NOW CLOBBERED
06700		POP	P,0		; RESTORE JFN TO AC0
06800		HRLI	0,400000 	; XWD FORK, JFN
06900	 	MOVE	16,-2(P) 	; THE INCREMENT -- NOTE THAT SP IS NOW CLOBBERED
07000		MOVE	17,[254000400010] 	; FOR COMPARISON -- NOTE THAT THE P STACK IS GONE
07100		JRST	4 		; AND GO
07200	A1:	-1 		; FOR PMAP
07300	A2:	400000000677 	; THIS FORK, START AT 677 (LEAVING EMULATOR)
07400	A3:	0 ;
07500	A4:	JSYS PMAP
07600	A5:	SOJL	2,4 	; LOOP THROUGH PAGES
07700	A6:	MOVE	1,0 	; XWD 400000,JFN
07800	A7:	JSYS GET ;
07900	A10:	MOVEI	1,400000 	; THIS FORK
08000	A11:	JSYS GEVEC 		; JSYS GET ENTRY VECTOR
08100	A12:	CAMN	2,17 	; DEC STYLE??
08200	A13:	  HRRZ	2,120 	; YES
08300	A14:	ADD	2,16 	; ADD THE INCREMREMENT
08400	A15:	JRST	(2) 	; AND START THE JOB
08500	
08600	RUNERR:	TDZA	1,[-1]	;ZERO 1 AND SKIP
08700	RUNRET:	SETO	1,	;INDICATE SUCCESS
08800		SUB	SP,X22
08900		SUB	P,X33
09000		JRST	@3(P)
09100	
09200	
09300		BEND;RUNPRG
09400	ENDCOM(RUNPRG)
     

00100	COMPIL(OPF,<OPENFILE,SETINPUT,SETPL,INDEXFILE,SETCHAN>,<.SKIP.>,<OPENFILE -- OPEN A FILE>)
00200	DSCR INTEGER SIMPLE PROCEDURE OPENFILE(STRING NAME,OPTIONS)
00300	
00400		Name is the name of the file to be opened.  If it is null, then
00500	OPENFILE goes to the user's console for the filname (with recognition).
00600		The value of the call is the jfn returned to the user.
00700		OPTIONS is a string of options available to the user.  Legal 
00800	characters are:
00900	
01000	One of these:
01100		R		read
01200		W		write
01300		A		append
01400	Version numbering
01500		O		old file
01600		N		new file
01700		T		temporary file
01800		*		index with INDEXFILE routine
01900	
02000	Independent:
02100		C		require confirmation
02200		D		ignore deleted bit
02300		H		"thawed" access
02400	Error handling
02500		E		return errors to user in the external
02600				integer !skip!.  TENEX error codes are used.
02700				(JFN will be released in this case.)
02800		OPENFILE does a GTJFN followed by a OPENF.  If GTJFN fails, a new
02900	attempt is made, from the user's console.  
03000	⊗
03100	
03200		BEGIN OPENFILE
03300	JFN←3				;WHERE TO PUT THINGS
03400	FLAGS←4
03500	GTFLAGS←5
03600	OPFLAGS←6
03700	
03800	DEFINE EQ $ (X,Y) <
03900		CAIE	A,"$X$"
04000		   JRST .+3
04100		TESTO	FLAGS,Y
04200		JRST	OPCONT
04300	>
04400	
04500	DEFINE JTRUE $ (X) <
04600		TESTN	FLAGS,X
04700	>
04800	DEFINE JFALSE (X) <
04900		TESTE	FLAGS,X
05000	>
05100	
05200	DEFINE 	SGT (X) <
05300		TESTO	GTFLAGS,X
05400	>
05500	DEFINE  SOF (X) <
05600		TESTO	OPFLAGS,X
05700	>
05800	DEFINE  TGT (X) <
05900		TESTE	FLAGS,X
06000		  TESTO GTFLAGS,X
06100	>
06200	DEFINE  TOP (X) <
06300		TESTE	FLAGS,X
06400		  TESTO OPFLAGS,X
06500	>
06600	
06700	HERE(OPENFILE)
06800		SETZB	FLAGS,.SKIP.
06900		SETZB	GTFLAGS,OPFLAGS
07000		HRRZ	B,-1(SP)		;COUNT OF OPTIONS WORD
07100	
07200	WHIOPT:	JUMPE	B,OPTDUN
07300		ILDB	A,(SP)			;GET AN OPTION
07400		CAIGE	A,141
07500		   JRST .+3
07600		CAIG	A,172
07700		   SUBI	A,40			;CONVERT TO UPPER CASE
07800	;ANY NON-ALPHABETIC CHARS GO HERE
07900	
08000		EQ 	*,STARBIT
08100	;NOW ALLOW ONLY ALPHABETIC CHARS
08200		CAIL	A,101			;MUST BE 
08300		CAILE	A,132
08400		   JRST	OPTERR
08500		SKIPN	BITTBL-"A"(A)		;SOMETHING THERE?
08600		   JRST	OPTERR			;NOPE, ERROR
08700		TDO	FLAGS,BITTBL-"A"(A)	;RIGHT SPOT IN TABLE
08800		SOJGE	B,WHIOPT
08900		  JRST	OPTDUN
09000	;HERE ON ERROR
09100	OPTERR:	ERR	<OPENFILE:  ILLEGAL OPTION >,1
09200		TESTO	FLAGS,ERSNBIT
09300	
09400	  OPCONT:
09500		SOJGE	B,WHIOPT
09600	
09700	;NOW SET UP GTFLAGS ACCORDING TO THE SCANNED INFORMATION
09800	OPTDUN:		
09900		TGT	OLDBIT			;INSIST ON OLD?
10000		TGT	NEWBIT			;INSIST ON NEW?
10100		JTRUE	OLDBIT
10200		JFALSE	NEWBIT			;IF NEITHER
10300		  JRST	OPTDU1			;WELL, ONE
10400		JTRUE	WRBIT			;IF WRITING
10500		  JRST	OPTDU1
10600		JFALSE	RDBIT			;AND READING
10700		JTRUE	APPBIT			;BUT NOT APPENDING
10800		  SGT	OUTBIT			;THEN SET OUTPUT BIT
10900	OPTDU1:
11000		JFALSE	RDBIT			;IF READING
11100		JFALSE	WRBIT			;AND NOT WRITING
11200		   JRST	OPTDU2	   
11300		JTRUE	APPBIT			;AND NOT APPENDING
11400		   SGT	OLDBIT			;THEN INSIST ON OLD
11500	OPTDU2:
11600	;NOW TEST FOR INDEPENDANT THINGS
11700		TOP	RDBIT
11800		TOP	WRBIT
11900		TOP	APPBIT
12000		TGT	TEMBIT
12100		TGT	STARBIT
12200		TGT	DELBIT
12300		TOP	THAWBIT
12400		JFALSE	CONFBIT
12500		   JRST	[SGT	CONFB1
12600			 SGT	CONFB2
12700			 JRST	.+1]
12800		TLO	GTFLAGS,1		;SHORT CALL OF GTJFN
12900	GTAGAIN:
13000		HRRZ	A,-3(SP)		;LENGTH OF NAME
13100		JUMPE	A,[TRYAGN:  
13200			   TLO	GTFLAGS,2
13300			   MOVE	2,[XWD 100,101]
13400			   JRST  GT]
13500		AND 	GTFLAGS,[717777777777]
13600		
13700		PUSH	SP,-3(SP)
13800		PUSH	SP,-3(SP)
13900		PUSH	P,[0]
14000		PUSHJ	P,CATCHR		;CONCATENATE A NULL CHAR
14100		MOVE	2,(SP)			;BYTE-POINTER
14200		SUB	SP,X22			;ADJUST STACK
14300	GT:	MOVE	1,GTFLAGS
14400		JSYS GTJFN
14500		  JRST 	GTERR
14600		MOVEM	1,JFN			;REMEMBER JFN
14700		PUSHJ	P,SETCHN		;SET A CHANNEL, ALLOCATE, GET CDB, SET DVTYP, RETURN CHANNEL
14800		MOVEM	1,CHNL			;REMEMBER CHANNEL	
14900		MOVEM	GTFLAGS,GFL(CDB)
15000	
15100	
15200	COMMENT ⊗ Do the open.
15300	⊗
15400		MOVE	1,DVTYP(CDB)		;CHECK THE DEVICE TYPE
15500		CAIE	1,7			;IS IT THE LPT?
15600		CAIN	1,12			;IS IT A TTY?
15700		   JRST	B7			;YES, USE 7 BIT
15800	B36:	HRRZ	1,JFN			;JFN
15900		HRRZ	2,OPFLAGS
16000		HRLI	2,440000		;36-BIT, MODE 0
16100		JSYS OPENF	
16200		   JRST	B36DMP			;TRY 36-BIT, DUMP MODE
16300		JRST	OPNOK
16400	B36DMP:	HRRZ	1,JFN
16500		HRRZ	2,OPFLAGS
16600		HRLI	2,447400		;36 BITS, DUMP MODE
16700		JSYS OPENF			
16800		   JRST	B7
16900		JRST	OPNOK
17000	B7:	HRRZ	1,JFN
17100		HRRZ	2,OPFLAGS
17200		HRLI	2,70000			;7 BIT
17300		JSYS OPENF
17400		    JRST OPERR			;NOPE
17500	OPNOK:	MOVEM	2,OFL(CDB)		;SAVE 
17600		MOVE	1,CHNL			;RETURN CHANNEL NO	
17700	OPFRET:	SUB	SP,X44			;ADJUST
17800		POPJ	P,			;AND RETURN
17900	
18000	
18100	
18200	
18300	GTERR:
18400	;HERE WITH ERROR ON GTJFN
18500		JTRUE	ERTNBIT			;USER WANT'S ERRORS?
18600		   JRST	GTER1			;NO
18700	ERRRET:	MOVEM	1,.SKIP.		;STORE FOR USER
18800		SETO	1,			;SOMETHING SUSPICIOUS
18900		JRST	OPFRET			;AND RETURN
19000	
19100	GTER1:	PUSHJ	P,SERSTR		;SHOW ERSTR
19200		HRROI	1,[ASCIZ/
19300	Cannot GTJFN file /]
19400		JSYS PSOUT
19500		PUSH	SP,-3(SP)
19600		PUSH	SP,-3(SP)
19700		PUSHJ	P,OUTSTR
19800		HRROI	1,[ASCIZ/, try again  */]
19900		JSYS PSOUT
20000		JRST	TRYAGN
20100	
20200	
20300	
20400	OPERR:	JTRUE	ERTNBIT
20500		   JRST	OPER1
20600		PUSH	P,1			;SAVE ERROR BITS
20700		PUSH	P,CHNL
20800		PUSHJ	P,CFILE			
20900		POP	P,1			;RESTORE ERROR BITS
21000		JRST	ERRRET
21100	
21200	OPER1:	PUSHJ	P,SERSTR		;SHOW ERSTR
21300		HRROI	1,[ASCIZ/
21400	Cannot OPENF file /]
21500		JSYS 	PSOUT
21600		PUSH	SP,-3(SP)
21700		PUSH	SP,-3(SP)
21800		PUSHJ	P,OUTSTR
21900		HRROI	1,[ASCIZ/, try again  */]
22000		JSYS 	PSOUT	
22100		PUSH	P,CHNL			;CLOSE AND RELEASE FILE AND CDB BLOCK
22200		PUSHJ	P,CFILE
22300		JRST	TRYAGN	
22400	
22500	;HERE WITH THE TENEX ERROR CODE IN 1 -- 1 MAY BE CLOBBERED
22600	SERSTR:
22700		PUSH	P,2			;SAVE ACS
22800		PUSH	P,3
22900		HRRZ	2,1
23000		HRLI	2,400000		;THIS FORK
23100		HRROI	1,[ASCIZ/
23200	/]
23300		JSYS	PSOUT
23400		MOVEI	1,101			;PRIMARY OUTPUT
23500		SETZ	3,			;FLAGS
23600		JSYS	ERSTR
23700		  JFCL
23800		  JFCL
23900		POP	P,3
24000		POP	P,2
24100		POPJ	P,
24200	
24300	
24400	BITTBL: APPBIT	;A
24500		BINBIT	;B
24600		CONFBIT	;C
24700		DELBIT	;D
24800		ERTNBIT	;E
24900		0	;F
25000		0	;G
25100		THAWBIT	;H
25200		0	;I
25300		0	;J
25400		0	;K
25500		0	;L
25600		0	;M
25700		NEWBIT	;N
25800		OLDBIT	;O
25900		0	;P
26000		0	;Q
26100		RDBIT	;R
26200		0	;S
26300		TEMBIT	;T
26400		0	;U
26500		0	;V
26600		WRBIT	;W
26700		0	;X
26800		0	;Y
26900		0	;Z
27000	
27100	
27200		BEND OPENFILE
27300	
     

00100	DSCR PROCEDURE SETINPUT(INTEGER CHAN; REFERENCE INTEGER COUNT,BR,EOF)
00200		Sets up the variables associated with input (as in the DEC
00300	open statement.)
00400	⊗
00500	
00600	HERE(SETINPUT)
00700		PUSHJ	P,SAVE
00800		VALCHN	1,-4(P),SETERR
00900		POP	P,TEMP
01000		POP	P,ENDFL(CDB)
01100		SKIPE	ENDFL(CDB)
01200		   SETZM @ENDFL(CDB)		;ASSUME NOT EOF
01300		POP	P,BRCHAR(CDB)
01400		SKIPE	BRCHAR(CDB)
01500		   SETZM @BRCHAR(CDB)		;ASSUME NO BRCHAR
01600		POP	P,ICOUNT(CDB)
01700		SETZ	LPSA,			;NO PARAMETERS
01800		SUB	P,X11
01900		JRST	RESTR
02000	SETERR: ERR <Illegal JFN>,1
02100		MOVE	LPSA,[XWD 5,5]
02200		JRST	RESTR
02300	
     

00100	DSCR
00200		SETPL(CHAN,@LINNUM,@PAGNUM,@SOSNUM)
00300	
00400		Names the variables to be used by the INPUT
00500	function for counting the line-feeds (12), formfeeds (14)
00600	seen by INPUT, as well as keeping the current SOS line
00700	number, if any.  Useful when scanning a file, and
00800	you want to know what page,line you are on.
00900		Initializes all three variables to 0.
01000	
01100	⊗
01200	HERE(SETPL)
01300		PUSHJ	P,SAVE
01400		VALCHN	1,-4(P),SETPER
01500		POP	P,TEMP		;RET ADR
01600		POP	P,SOSNUM(CDB)
01700		SETZM	@SOSNUM(CDB)
01800		POP	P,PAGNUM(CDB)
01900		SETZM	@PAGNUM(CDB)
02000		POP	P,LINNUM(CDB)
02100		SETZM	@LINNUM(CDB)
02200		SUB	P,X11		;REMOVE CHANNEL NO.
02300	SETRET:	SETZ	LPSA,
02400		JRST	RESTR
02500	SETPER: ERR <Illegal JFN>,1
02600		MOVE	LPSA,[XWD 5,5]
02700		JRST	RESTR
02800	
02900	
03000	
03100	
     

00100	DSCR
00200		BOOLEAN PROCEDURE INDEXFILE(INTEGER JFN)
00300	
00400	RETURNS TRUE AS LONG AS WE CAN GNJFN ANOTHER FILE
00500	⊗
00600	
00700	HERE(INDEXFILE)
00800		PUSH	P,-1(P)
00900		PUSHJ	P,CLOSF
01000		PUSH	P,-1(P)
01100		PUSHJ	P,GNJFN
01200		JUMPE	1,INDRET		;RETURN FALSE IF NO OTHER FILES
01300		PUSH	P,2
01400		PUSH	P,CDB
01500		PUSH	P,CHNL		
01600	;CHANNEL ALREADY VALID
01700		MOVE	CHNL,-4(P)			;CHANNEL NUMBER
01800		MOVE	CDB,CDBTBL(CHNL)		;CDB LOC
01900		HRRZ	1,JFNTBL(CHNL)		;JFN
02000		MOVE	2,OFL(CDB)		;GET OPENFLAGS
02100		JSYS OPENF			;TRY OPENING
02200		  JRST NOIND
02300		SKIPE	ENDFL(CDB)		;ZERO SETINPUT (or OPEN) VARIABLES IF HERE
02400		  SETZM	@ENDFL(CDB)
02500		SKIPE	BRCHAR(CDB)
02600		  SETZM	@BRCHAR(CDB)
02700		SKIPE	LINNUM(CDB)		;ZERO SETPL VARS
02800		  SETZM	@LINNUM(CDB)
02900		SKIPE	PAGNUM(CDB)
03000		  SETZM	@PAGNUM(CDB)
03100		SKIPE	SOSNUM(CDB)
03200		  SETZM	@SOSNUM(CDB)
03300		SETO	1,
03400	INDPOP:	POP	P,CHNL
03500		POP	P,CDB
03600		POP	P,2
03700	INDRET:	SUB	P,X22	
03800		JRST	@2(P)
03900	
04000	NOIND:	ERR <INDEXFILE:  CANNOT OPENF>,1
04100		SETZ	1,
04200		JRST	INDPOP
     

00100	DSCR SETCHAN(JFN,GTFLAGS,OPFLAGS)
00200	
00300		JFN is a real TENEX jfn.  It is inserted in the SAIL
00400	runtime system, and the internal book-keeping is set to
00500	believe that the GTJFN was done with GTFLAGS and the OPENF
00600	with OPFLAGS.  JFN may have come from some random source.
00700	⊗
00800	HERE(SETCHAN)
00900		PUSHJ	P,SAVE
01000		MOVE	LPSA,X44
01100		MOVE	A,-3(P)				;JFN
01200		PUSHJ	P,SETCHN
01300		MOVEM	A,RACS+A(USER)			;CHANNEL
01400		HRROI	A,-1(P)				;PREPARE FOR POPPING
01500		POP	A,OFL(CDB)			;MOVE FROM THE STACK
01600		POP	A,GFL(CDB)
01700		JRST	RESTR
01800	
01900	ENDCOM(OPF)
     

00100	COMPIL(GTJFN,<GTJFN,GTJFNL>,<.SKIP.,SETCHN,CATCHR,X11,X22,X44>,<GTJFN -- GET A JFN>)
00200	DSCR INTEGER SIMPLE PROCEDURE GTJFN(STRING S; INTEGER FLAGS)
00300		Does a GTJFN.  If S is non-null, it is the filename, otherwise
00400	the routine goes to the user's console for a file.  FLAGS are used for
00500	accumulator 1, and any error code is returned in .SKIP.  The value
00600	of the call is the JFN, if obtained.
00700		Defaults for FLAGS:  0  means ordinary input, 1 means ordinary
00800	output.  Ordinarily the user will use the OPENFI routine.
00900	⊗
01000	
01100	HERE(GTJFN)
01200		SKIPN	1,-1(P)
01300		  MOVSI 1,100001
01400		CAIN	1,1
01500		  MOVSI	1,600001
01600		TLO	1,1			;MARK FOR SHORT CALL
01700		HRRZ	2,-1(SP)
01800		JUMPE	2,[MOVE 2,[100000101]
01900			  TLO	1,2		;INDICATE XWD JFN,JFN IN 2
02000			   JRST GOTDEST]
02100		TLZ	1,2			;INDICATE BYTE-POINTER IN 2
02200		PUSH	P,[0]			
02300		PUSHJ	P,CATCHR		;PUT ON A NULL
02400		MOVE	2,(SP)
02500	GOTDEST: SETZM	.SKIP.			;ASSUME NO ERROR
02600		PUSH	P,1			;SAVE FLAGS
02700		JSYS GTJFN
02800		  JRST GTBAD 		; SOMETHING IS WRONG
02900		PUSHJ	P,SETCHN	;SETUP A CHANNEL, AND ALLOCATE, GET STATUS, SET CDB
03000		POP	P,GFL(CDB)	;SAVE FLAGS
03100	GTRET:	SUB	SP,X22
03200		SUB	P,X22
03300		JRST	@2(P)
03400	
03500	GTBAD:
03600		
03700		MOVEM 	1,.SKIP.		; REMEMBER
03800		POP	P,1			;ADJUST STACK
03900		SETO 	1, 		; SOMETHING SUSPICIOUS TO RETURN TO USER
04000		JRST	GTRET
04100	
     

00100	DSCR INTEGER PROCEDURE GTJFNL(STRING ORIG; INTEGER FLAGS, XWDJFN!JFN;
00200		STRING DEV,DIR,NAM,EXT,PROT,ACCOUNT; INTEGER DESIRED!JFN)
00300	
00400		Does the long form of GTJFN.  
00500	⊗
00600	HERE(GTJFNL)
00700		BEGIN GTJFNL
00800	
00900	DEFINE STRPUT(X)<
01000		PUSHJ	P,.STPUT
01100		MOVEM	A,X
01200	>
01300	DEFINE FLG <-14(P)>
01400	DEFINE IOJFN <-13(P)>
01500	DEFINE DESJFN <-12(P)>
01600		ADD	P,[XWD 11,11]		;ROOM FOR LONG-FORM TABLE
01700		TLNN	P,400000		;OVERFLOW?
01800		  ERR	<GTJFNL:  P-stack overflow>
01900		MOVE	A,DESJFN	
02000		MOVEM	A,0(P)			;THE DESIRED JFN
02100		STRPUT	-1(P)			;ACCOUNT
02200		STRPUT	-2(P)			;PROTECTION
02300		STRPUT	-3(P)			;EXTENSION
02400		STRPUT	-4(P)			;NAME
02500		STRPUT	-5(P)			;DIRECTORY
02600		STRPUT	-6(P)			;DEVICE
02700		MOVE	A,IOJFN			;XWD INPUT JFN, OUTPUT JFN
02800		MOVEM	A,-7(P)
02900		MOVE	A,FLG	
03000		MOVEM	A,-10(P)
03100		STRPUT	B			;MAIN STRING POINTER
03200		MOVEI	A,-10(P)		;ADDRESS OF BLOCK (ON STACK)
03300		SETZM	.SKIP.			;ASSUME NO ERROR
03400		JSYS	GTJFN			;LONG FORM
03500		   JRST	GTLBAD			;NOPE
03600		PUSHJ	P,SETCHN		;SET UP CHANNEL TABLE, ALLOCATE, GET STATUS, SET CDB
03700		MOVE	B,-10(P)		;GTJFN FLAGS
03800		MOVEM	B,GFL(CDB)		;SAVE
03900	GTLRET:	SUB	P,[XWD 11+4,11+4]	;ADJUST STACK FOR LONG-FORM TABLE, AND ARGUMENTS
04000		JRST	@4(P)			;AND RETURN
04100	
04200	GTLBAD:	MOVEM	A,.SKIP.		;RETURN ERROR CODE TO USER
04300		SETO	A,			;SOMETHING SUSPICIOUS
04400		JRST	GTLRET			;AND RETURN
04500	
04600	.STPUT:	HRRZ	A,-1(SP)		;GET THE COUNT
04700		  JUMPE	A,[SUB	SP,X22		;ADJUST AND RETURN
04800			   POPJ	P,]
04900		PUSH	P,[0]
05000		PUSHJ	P,CATCHR
05100		POP	SP,A
05200		SUB	SP,X11
05300		POPJ	P,
05400	
05500	
05600		BEND GTJFNL
05700	
05800	
05900	
06000	ENDCOM(GTJFN)
     

00100	COMPIL(FILINF,<GNJFN,DELF,UNDELETE,DELNF,SIZEF,JFNS,JFNSL,OPENF,CFILE,CLOSF,RLJFN,GTSTS,STSTS,RNAMF>
00200		,<JFNTBL,CDBTBL,X11,X22,X33,CORREL,.SKIP.,ZSETST,ZADJST,FINIO>
00300		,<FILINF -- UTILITY FILE ROUTINES>)
00400	
00500	
00600	DSCR INTEGER SIMPLE PROCEDURE GNJFN(INTEGER JFN)
00700		Does the GNJFN jsys.
00800	⊗
00900	HERE(GNJFN)
01000		PUSHJ	P,SAVE
01100		MOVE	LPSA,X22
01200		VALCHN 1,<-1(P)>,GNERR
01300		MOVE	1,JFNTBL(CHNL)		;GET THE WHOLE JFN
01400		JSYS	GNJFN
01500		  JRST	GNRLZ			;FAILURE TO INDEX, RELEASE JFN
01600		MOVEM	1,.SKIP.		;SAVE BITS INDICATING CHANGE
01700		SETOM	RACS+A(USER)		;INDICATE SUCCESS
01800	GNRET:	JRST	RESTR
01900	
02000	GNERR:  ERR <Illegal JFN>,1
02100		SETZM	RACS+A(USER)
02200		JRST	RESTR
02300	
02400	GNRLZ:	SETZM	.SKIP.			;NOTHING THERE
02500		SETZM	RACS+A(USER)		;FAILURE TO INDEX
02600		PUSH	P,-1(P)
02700		PUSHJ	P,CFILE			;SO RELEASE FILE
02800		JRST	RESTR
02900	
     

00100	DSCR	PROCEDURE DELF(INTEGER CHAN)
00200		Deletes file open on CHAN.  Errors to .SKIP. 
00300	⊗
00400	HERE(DELF)
00500		PUSH	P,1
00600		VALCH1	1,-2(P),DELF1
00700		TLO	1,400000		;DONT RELEASE THE JFN
00800		JSYS	DELF
00900		  JRST	DELF2
01000		SETZM	.SKIP.			;NO ERROR
01100	DELFRE:	POP	P,1
01200		SUB	P,X22
01300		JRST	@2(P)
01400	DELF1:	SETO	1,
01500	DELF2:	MOVEM	1,.SKIP.
01600		JRST	DELFRE
01700	
01800	DSCR INTEGER PROCEDURE DELNF(INTEGER CHAN,NUM)
01900	⊗
02000	HERE(DELNF)
02100		PUSHJ	P,SAVE
02200		MOVE	LPSA,X33
02300		VALCH1	1,-2(P),DLNERR
02400		MOVE	2,-1(P)
02500		SETZM	.SKIP.
02600		JSYS	DELNF
02700		  JRST	DLNERR
02800		MOVM	2,2			;ABSOLUTE NUMBER OF
02900		MOVEM	2,RACS+A(USER)		;FILES DELETED
03000		JRST	RESTR	
03100	DLNERR:	MOVEM	1,.SKIP.;
03200		SETZM	RACS+A(USER)		;INDICATE NO FILES DELETED
03300		JRST	RESTR
     

00100	DSCR	PROCEDURE UNDELETE(INTEGER CHAN)
00200		Undeletes file open on CHAN.  Errors to .SKIP.
00300	⊗
00400	HERE(UNDELETE)
00500		PUSHJ	P,SAVE
00600		MOVE	LPSA,X22
00700		VALCH1	1,-1(P),UNDEL1
00800		HRLI	1,1			;XWD 1,JFN
00900		MOVSI	2,(1B3)			;DELETED BIT
01000		SETZ	3,			;TURN IT OFF
01100		JSYS	CHFDB			;CHANGE THE FDB
01200		JRST	RESTR
01300	UNDEL1:	SETOM	.SKIP.
01400		JRST	RESTR
01500		
01600	
01700	
01800	
     

00100	DSCR	INTEGER PROCEDURE SIZEF(INTEGER JFN)
00200		Gets the size in pages of the file open on JFN, with error code to 
00300	.SKIP.
00400	⊗
00500	HERE(SIZEF)
00600		PUSHJ	P,SAVE
00700		MOVE	LPSA,X22
00800		VALCHN 1,<-1(P)>,SIZERR
00900		SETZM	.SKIP.
01000		JSYS SIZEF
01100		JRST [MOVEM 1,.SKIP.
01200			SETZM	RACS+A(USER)
01300			JRST SIZRET]
01400		MOVEM	3,RACS+A(USER)		;ANSWER IN AC 3
01500	SIZRET:	JRST	RESTR
01600	
01700	SIZERR: ERR <Illegal JFN>
01800		SETOM	.SKIP.
01900		JRST	SIZRET
02000	
02100	
     

00100	
00200	DSCR STRING SIMPLE PROCEDURE JFNS(INTEGER JFN,FLAGS)
00300		Returns the name of the file associated with JFN.
00400	FLAGS are for ac 3 as described in the jsys manual, with
00500	0 the reasonable default.
00600	⊗
00700	
00800	HERE(JFNS)
00900		VALCHN	2,<-2(P)>,JFNSER	;GET JFN IN AC2
01000		PUSH	P,[=400]
01100		PUSHJ	P,ZSETST		;GET BP IN AC 1
01200		MOVE	3,-1(P)
01300		JSYS JFNS
01400		PUSH	P,[=400]
01500		PUSH	P,1
01600		PUSHJ	P,ZADJST
01700	JFNSRE:	SUB	P,X33
01800		JRST	@3(P)
01900	JFNSER: ERR <Illegal JFN>,1
02000		PUSH	SP,[0]			;RETURN NULL STRING
02100		PUSH	SP,[0]
02200		JRST	JFNSRE
02300	
02400	
02500	DSCR JFNSL is added to correct a design error in JFNS, which did
02600	not allow full flexibility.
02700	⊗
02800	
02900	HERE(JFNSL)
03000		BEGIN JFNSL
03100		VALCHN	2,<-3(P)>,JFNSER	;VALIDATE, GETTING JFN IN 2
03200		MOVE	1,-1(P)			;FLAGS FOR LH
03300		CAMN	1,[-1]			;-1??
03400		 HLRZ	1,JFNTBL(CHNL)		;YES, GET THOSE USED BY GTJFN
03500		HRL	2,1			;NOW PUT FLAGS INTO LH(2)
03600		PUSH	P,[=400]
03700		PUSHJ	P,ZSETST		;GET BP IN AC 1
03800		MOVE	3,-2(P)			;CONTROL FLAGS FOR FORMAT
03900		JSYS JFNS
04000		PUSH	P,[=400]
04100		PUSH	P,1
04200		PUSHJ	P,ZADJST
04300	JFNSRE:	SUB	P,[XWD 4,4]
04400		JRST	@4(P)
04500	JFNSER: ERR <Illegal JFN>,1
04600		PUSH	SP,[0]			;RETURN NULL STRING
04700		PUSH	SP,[0]
04800		JRST	JFNSRE
04900	
05000		BEND JFNSL
     

00100	DSCR SIMPLE PROCEDURE OPENF(INTEGER JFN,FLAGS)
00200		Does an OPENF.
00300	
00400	PARAMETERS:
00500		JFN     the JFN
00600		FLAGS 	for accumulator 2.
00700		.SKIP.	the error code (if pertinent)
00800	
00900	Some defaults:
01000		FLAGS		ACTION
01100		-----------------------
01200		0		INPUT CHARACTERS
01300		1		OUTPUT CHARACTERS
01400		2		INPUT 36-BIT WORDS
01500		3		OUTPUT 36-BIT WORDS
01600		4		DUMP MODE INPUT (USE DUMPI FUNCTION)
01700		5		DUMP MODE OUTPUT (USE DUMPO FUNCTION)
01800		VALUES 6-10 ARE RESERVED FOR EXPANSION
01900	
02000	Other values of FLAGS are interpreted literally.
02100		Ordinarily the user will use the OPENFI routine.
02200	⊗
02300	
02400	HERE(OPENF)
02500		PUSHJ	P,SAVE
02600		MOVE	LPSA,X33
02700		VALCHN	1,-2(P),OPNERR
02800		SKIPL	2,-1(P)		;GET THE FLAGS
02900		CAILE	2,5		;CHECK IN RANGE 0-5
03000		   JRST	GOTFLAGS
03100		MOVE	2,OPNTBL(2)	;GET CORRECT WORD
03200	GOTFLAGS:
03300		SETZM	.SKIP.
03400		PUSH	P,2		;SAVE FLAGS
03500		JSYS OPENF
03600		  JRST	NOOPN
03700		POP     P,OFL(CDB)	;AND SAVE FLAGS
03800		SETZM	IOSTT(CDB)	;CLEAR STATUS
03900	OPNRET:	JRST	RESTR
04000	
04100	OPNERR: ERR <Illegal JFN>,1
04200		SETOM	.SKIP.
04300		JRST	OPNRET
04400	
04500	NOOPN:	MOVEM	1,.SKIP.
04600		SUB	P,X11		;ADJUST STACK
04700		JRST	OPNRET
04800	
04900	OPNTBL:	070000200000		;7-BIT READ
05000		070000100000		;7-BIT WRITE
05100		440000200000		;36-BIT READ
05200		440000100000		;36-BIT WRITE
05300		447400200000		;36-BIT DUMP READ
05400		447400100000		;36-BIT DUMP WRITE
     

00100	
00200	DSCR SIMPLE INTEGER PROCEDURE CFILE(INTEGER JFN)
00300		Closes the file (CLOSF) and releases (RLFJN)
00400	the jfn.  This is the ordinary way the user will use
00500	to dispense with a file.
00600		Returns TRUE if JFN legal and released, FALSE o.w.
00700	Always returns.
00800	⊗
00900	
01000	HERE(CFILE)
01100		PUSH	P,2
01200		PUSH	P,3
01300		PUSH	P,CHNL
01400		PUSH	P,CDB
01500		SKIPL	CHNL,-5(P)
01600		CAIL	CHNL,JFNSIZE
01700		   JRST	CFBAD
01800		MOVE	CDB,CDBTBL(CHNL)	;GET CDB
01900		SKIPN	1,JFNTBL(CHNL)	;JFN ASSIGNED?
02000		   JRST	CFBA1		;NO, JUST RELEASE CORE
02100		HRRZ	1,1		;JFN ONLY
02200		PUSHJ	P,FINIO		;WRITE OUT REMAINING STUFF, CHECK EOF, MAGTAPE
02300	
02400	RLCOR:	SKIPE	B,CDBTBL(CHNL)	; ANY CORE TO RELEASE?
02500		  PUSHJ	P,CORREL	; RELEASE THE BLOCK
02600		TLZ	1,400000	; BE SURE TO RELEASE
02700		JSYS CLOSF		; CLOSE (AND RELEASE)
02800		   JFCL			; ERROR RETURN
02900		HRRZ	1,JFNTBL(CHNL)	; GET JFN AGAIN
03000		JSYS	RLJFN		; RELEASE (FOR GOOD MEASURE IF FILE NOT OPEN)
03100		   JFCL			; ERROR RETURN
03200		SETO	1, 		; RETURN TRUE FOR GOOD RELEASE
03300	      	SETZM	CDBTBL(CHNL)
03400		SETZM	JFNTBL(CHNL)
03500	CFRET:	POP	P,CDB
03600		POP	P,CHNL
03700		POP	P,3
03800		POP	P,2
03900		SUB	P,X22 		; ADJUST
04000		JRST	@2(P) 		; RETURN
04100	
04200	CFBAD:	SETZ	1, 		; RETURN FALSE
04300		JRST	CFRET ;
04400	
04500	CFBA1:	SKIPE	B,CDB
04600		PUSHJ	P,CORREL	;RELEASE CORE BLOCK
04700		SETZM	CDBTBL(CHNL)	;REMOVE ALL TRACE
04800		SETZM	JFNTBL(CHNL)	
04900		SETZ	1,		; RETURN FALSE
05000		JRST	CFRET
05100	
     

00100	DSCR SIMPLE PROCEDURE CLOSF(INTEGER JFN)
00200		Does a CLOSF on the JFN.  Ordinarily the user
00300	will want to use the CFILE routine, which handles errors
00400	internally. The CLOSF is accomplished in such a way that
00500	the JFN is actually not released.
00600		If the device is a magtape open for output, then
00700	2 eof's are written, followed by a backspace.  This writes
00800	a standard end-of-file on the tape.
00900	⊗
01000	HERE(CLOSF)
01100		PUSHJ	P,SAVE
01200		MOVE	LPSA,X22
01300		VALCHN	1,<-1(P)>,CLOERR
01400		PUSHJ	P,FINIO		;WRITE OUT BUFFERS, SET FDB, WRITE MAGT EOFS, CLEAR BUFFERS
01500	
01600	DOCLO:	SETZM 	.SKIP.		;ASSUME NO ERROR
01700		TLO 1,400000 		; DO NOT RELEASE THE JFN
01800		JSYS CLOSF
01900		  MOVEM	1,.SKIP.	;ERROR
02000	CLORET:	JRST	RESTR
02100	
02200	CLOERR:	
02300		SETOM	.SKIP.
02400		JRST	CLORET
02500	
     

00100	DSCR SIMPLE PROCEDURE RLJFN(INTEGER JFN)
00200		Does the RLJFN jsys.  Ordinarily the user will want
00300	to use the CFILE routine, which handles errors internally.
00400	⊗
00500	
00600	HERE(RLJFN)
00700		PUSHJ	P,SAVE
00800		MOVE	LPSA,X22
00900		SKIPL	C,-1(P)
01000		CAIL	C,JFNSIZE
01100		   JRST	RLJBAD
01200		SKIPN	1,JFNTBL(C)
01300	 	   JRST	RLJBAD
01400		SETZM	JFNTBL(C)	
01500		SKIPE	B,CDBTBL(C)
01600		PUSHJ	P,CORREL
01700		SETZM	CDBTBL(C)
01800		SETZM	.SKIP.		;ASSUME NO ERROR
01900		JSYS RLJFN
02000		  MOVEM	1,.SKIP.	;ERROR RETURN
02100	RLJRET:	JRST	RESTR
02200	
02300	RLJBAD: ERR <Illegal JFN>,1
02400		SETOM 	.SKIP.
02500		JRST	RLJRET
02600	
02700	
     

00100	DSCR INTEGER SIMPLE PROCEDURE GTSTS(INTEGER JFN);
00200		Gets the file status. 
00300		WARNING: The results of this call are not necessarily appropriate
00400	if the file is open in special character input mode.  If you want to check
00500	for end-of-file, examine the EOF variable instead.
00600	⊗
00700	
00800	HERE(GTSTS)
00900		PUSHJ	P,SAVE
01000		MOVE	LPSA,X22
01100		VALCHN	1,<-1(P)>,GTSERR
01200		JSYS GTSTS
01300		MOVEM	2,RACS+A(USER)
01400	GTSRET:	JRST	RESTR
01500	
01600	GTSERR:	ERR <Illegal JFN>,1
01700		JRST	GTSRET
     

00100	DSCR BOOLEAN SIMPLE PROCEDURE STSTS(INTEGER JFN,STATUS);
00200		Sets the status of JFN to STATUS using the STSTS jsys.
00300	⊗
00400	
00500	HERE(STSTS)
00600		VALCH1 	1,<-2(P)>,STSERR
00700		MOVE	2,-1(P)
00800		SETO	3,			;ASSUME	SKIP
00900		SETZM	.SKIP.
01000		JSYS	STSTS
01100		  JRST [STERRT: SETZ	3,			;PROBLEM	
01200			MOVEM	1,.SKIP.
01300			JRST .+1]
01400		MOVE	1,3			;RETURN
01500		SUB	P,X33
01600		JRST	@3(P)
01700	
01800	STSERR:	ERR <Illegal JFN>,1
01900		JRST	STERRT			;RETURN
02000	
     

00100	DSCR BOOLEAN SIMPLE PROCEDURE RNAMF(INTEGER EXISTINGJFN,NEWJFN);
00200		File open on EXISTINGJFN is renamed to file open
00300	on NEWJFN.
00400	⊗
00500	HERE(RNAMF)
00600		VALCH1	1,<-2(P)>,RNFERR
00700		VALCH1	2,<-1(P)>,RNFERR
00800		SETO	3,			;ASSUME OK
00900		SETZM	.SKIP.
01000		JSYS	RNAMF
01100		   JRST [RNERET:  SETZ	3,
01200			 MOVEM	1,.SKIP.
01300			 JRST	.+1]
01400	RNFRET:	MOVE	1,3			;RETURN VALUE
01500		SUB	P,X33
01600		JRST	@3(P)
01700	
01800	RNFERR:	ERR <Illegal JFN>,1
01900		JRST	RNERET
02000	
02100	ENDCOM(FILINF)	
     

00100	COMPIL(DEVINF,<CNDIR,ASND,RELD,GDSTS,SDSTS,STDEV,DEVST,GTFDB,CHFDB>
00200		,<JFNTBL,CDBTBL,X11,X22,X33,CORREL,.SKIP.,ZSETST,ZADJST>
00300		,<DEVINF -- DEVICE AND DIRECTORY ROUTINES>)
00400	
00500	DSCR BOOLEAN SIMPLE PROCEDURE CNDIR(INTEGER DIR; STRING PASSWORD);
00600		Using the CNDIR jsys, connects to TENEX directory DIR (for
00700	AC1.)  PASSWORD is the password, which will usually be null, as
00800	in the EXEC CONNECT command.
00900	⊗
01000	
01100	HERE(CNDIR)
01200		PUSH	P,[0]
01300		PUSHJ	P,CATCHR		;PUT A NULL ON THE END OF THE PASSWORD
01400		POP	SP,2			;GET BP IN 2
01500		SUB	SP,X11			;CLEAN UP SP STACK
01600		MOVE	1,-1(P)			;DIRECTORY NO 
01700		SETO	3,			;ASSUME SUCCESS
01800		SETZM	.SKIP.
01900		JSYS	CNDIR
02000		  JRST	[SETZ 3,
02100			 MOVEM	1,.SKIP.
02200			 JRST	.+1]
02300		MOVE	1,3
02400		SUB	P,X22
02500		JRST	@2(P)
02600	
     

00100	DSCR BOOLEAN PROCEDURE ASND(INTEGER DEVICE)
00200		Assigns the device specified by DEVICE using the ASND jsys.
00300	Returns TRUE if successful, else error code in .SKIP.
00400	⊗	
00500	
00600	HERE(ASND)
00700		MOVE	1,-1(P)			;GET DEVICE DESIGNATOR
00800		JSYS	ASND
00900		  JRST	[MOVEM 1,.SKIP.
01000			 SETZ	1,
01100			 JRST .+2]
01200		SETO	1,
01300		SUB	P,X22
01400		JRST	@2(P)
     

00100	DSCR BOOLEAN PROCEDURE RELD(INTEGER DEVICE)
00200		Releases DEVICE using the RELD jsys.  If DEVICE is -1,
00300	then releases all devices assigned to this job.
00400	⊗
00500		
00600	HERE(RELD)
00700		MOVE	1,-1(P)
00800		JSYS	RELD
00900		  JRST	[MOVEM	1,.SKIP.
01000			 SETZ	1,
01100			 JRST	.+2]
01200		SETO	1,
01300		SUB	P,X22
01400		JRST	@2(P)
     

00100	DSCR INTEGER SIMPLE PROCEDURE GDSTS(INTEGER CHAN; REFERENCE INTEGER WORDCNT)
00200		Returns the device status of device open on CHAN using the GDSTS
00300	jsys.  The LH of WORDCNT has the word count of the last transfer completed,
00400	negative if the last transfer completed unsuccessful.
00500	⊗
00600	
00700	HERE(GDSTS)
00800		VALCH1	1,<-2(P)>,GDSERR
00900		SETZM	.SKIP.
01000		JSYS	GDSTS
01100		MOVEM	3,@-1(P)			;REFERENCE ARG
01200		MOVE	1,2				;RETURN VALUE
01300	GDSRET:	SUB	P,X33
01400		JRST	@3(P)
01500	GDSERR:	ERR <Illegal JFN>,1
01600		SETOM	.SKIP.	
01700		SETZ	1,		
01800		JRST	GDSRET
     

00100	DSCR PROCEDURE SDSTS(INTEGER JFN,NEWSTATUS)
00200	⊗
00300	HERE(SDSTS)
00400		VALCH1	1,<-2(P)>,SDSERR
00500		SETZM	.SKIP.				;INDICATE NO ERROR
00600		MOVE	2,-1(P)
00700		JSYS	SDSTS
00800	SDSRET:	SUB	P,X33
00900		JRST	@3(P)
01000	SDSERR:	ERR	<Illegal JFN>,1
01100		SETOM	.SKIP.
01200		JRST	SDSRET
     

00100	DSCR INTEGER PROCEDURE STDEV(STRING S)
00200		S is a string pointer to a string of the form DTA1.
00300	The device designator is returned.
00400	⊗
00500	
00600	HERE(STDEV)
00700		PUSH	P,[0]
00800		PUSHJ	P,CATCHR
00900		POP	SP,1
01000		SUB	SP,X11			;CLEAN SP STACK
01100		SETZM	.SKIP.
01200		JSYS	STDEV
01300		  JRST	[PUSHJ	P,SAVE		;GET FRESH ACS
01400			 MOVEI	1,400000	;THIS FORK
01500			 JSYS 	GETER		;GET ERROR NUMBER
01600			 HRRZM	2,.SKIP.	;SAVE IN .SKIP. FOR USER
01700			 SETZM	RACS+1(USER)	;ZERO RETURN
01800			 SETZ	LPSA,		;NOTHING TO REMOVE FROM STACK
01900			 JRST	RESTR		;AND RETURN
02000			]
02100		MOVE	1,2
02200		POPJ	P,
02300	
     

00100	
00200	DSCR STRING PROCEDURE DEVST(INTEGER DEVICE)
00300	⊗
00400	HERE(DEVST)
00500		PUSH	P,[=100]
00600		PUSHJ	P,ZSETST		;GET A BP FOR 100 CHARS
00700		SETZM	.SKIP.
00800		MOVE	2,-1(P)
00900		JSYS	DEVST
01000		  MOVEM	2,.SKIP.		;INDICATE ERROR
01100		PUSH	P,[=100]
01200		PUSH	P,1			;UPDATED BP
01300		PUSHJ	P,ZADJST
01400		SUB	P,X22
01500		JRST	@2(P)
01600		
     

00100	DSCR	SIMPLE PROCEDURE GTFDB(INTEGER JFN; REFERENCE INTEGER ARRAY BUF)
00200	
00300		Entire FDB of JFN is read into BUF.  No bounds checking,
00400	so BUF should be at least '26 words.
00500	⊗
00600	HERE(GTFDB)
00700		PUSHJ	P,SAVE
00800		MOVE	LPSA,X33
00900		VALCHN	1,<-2(P)>,FDBAD
01000		MOVSI	2,25		;ALL 25 WORDS
01100		HRRZ 	3,-1(P)		;ADDRESS OF ARRAY
01200		JSYS GTFDB
01300		JRST	RESTR
01400	
01500	FDBAD: ERR <Illegal JFN>,1
01600		JRST	RESTR
01700	
01800	HERE(CHFDB)
01900	DSCR
02000		CHFDB(CHAN,DISPLACEMENT,MASK,CHANGED!BITS)
02100	⊗
02200		PUSHJ	P,SAVE
02300		MOVE	LPSA,[XWD 5,5]
02400		VALCHN	1,-4(P),FDBAD		;GET JFN TO 1
02500		HRL	1,-3(P)			;DISPLACEMENT TO LEFT HALF OF ONE
02600		MOVE	2,-2(P)
02700		MOVE	3,-1(P)
02800		JSYS	CHFDB
02900		JRST	RESTR
03000	
     

00100	
00200	ENDCOM(DEVINF)
00300	
00400	DEFINE WORDROU < WORDIN,ARRYIN,WORDOUT,ARRYOUT,RWDPTR,SWDPTR >
00500	DEFINE CHARROU < CHARIN,SINI,INPUT,LREALIN,LREALSCAN,REALIN,REALSCAN,INTIN,INTSCAN,CHAROUT,OUT,LINOUT,RCHPTR,SCHPTR >
00600	DEFINE UTILROU < FINIO >
00700	
00800	COMPIL(IOROU,<WORDROU,CHARROU,UTILROU>
00900		,<JFNTBL,CDBTBL,X22,X33,X44,.SKIP.,SAVE,RESTR>
01000		,<IOROU -- Input and output routines>)	
01100	
     

00100	DSCR INTEGER SIMPLE PROCEDURE WORDIN(INTEGER JFN);
00200		Reads a word in from the file
00300	⊗
00400	HERE(WORDIN)
00500		BEGIN WORDIN
00600	
00700		PUSHJ	P,SAVE
00800		MOVE	LPSA,X22
00900		VALCHN	1,-1(P),WERR
01000		SETZEOF					;INDICATE NO EOF
01100	
01200	DOSIMIO:SIMIO	2,TABL,WERR			;SOSGE IOCNT(CDB)
01300		  JRST	.ADWI
01400		ILDB	2,IOBP(CDB)	
01500	STOAC2:	MOVEM	2,RACS+A(USER)
01600		JRST	RESTR
01700	
01800	DOBIN:	JSYS	BIN
01900		JUMPN	2,STOAC2			;CANNOT BE END OF FILE
02000	CHKEOF:	SETZM	RACS+A(USER)			;RETURN 0 IN ANY EVENT
02100		JSYS	GTSTS
02200		TESTE	2,1B8				;EOF?
02300		   JRST	INPEOF				;YES, INDICATE
02400		JRST	RESTR
02500	
02600	TABL:	JRST	DOSETWI				;0 -- SET UP
02700		JRST	.CISWI				;1 -- XICHAR
02800		JRST	.COSWI				;2 -- XOCHAR
02900		SOSGE	IOCNT(CDB)			;3 -- XIWORD
03000		JRST	.WOSWI				;4 -- XOWORD
03100		JRST	WERR				;5 -- XCICHAR
03200		JRST	WERR				;6 -- XCOCHAR
03300		JRST	DOBIN				;7 -- XCWORD
03400		REPEAT 4,<JRST WERR>			;10-13
03500	
03600	DOSETWI:
03700		PUSHJ	P,SETWI
03800		JRST	DOSIMIO
03900	
04000	
04100	.ADWI:	PUSHJ	P,ADWI
04200		  JRST	.ADEOF			;END OF FILE
04300		JRST	DOSIMIO				;START OVER
04400	
04500	.ADEOF:	SETZM	RACS+A(USER)			;RETURN 0 WORD
04600		JRST	INPEOF				;AND INDICATE EOF
04700	WERR:  	ERR	<Dryrot at WORDIN>,1
04800		SETZM	RACS+A(USER)
04900		JRST	INPEOF				;INDICATING EOF OR ERROR
05000	
05100	.CISWI:	PUSHJ	P,CISWI
05200		JRST	DOSIMIO
05300	
05400	.COSWI:	PUSHJ	P,COSWI
05500		JRST	DOSIMIO
05600	
05700	.WOSWI:	PUSHJ	P,WOSWI
05800		JRST	DOSIMIO
05900	
06000	
06100		BEND WORDIN
     

00100	HERE(ARRYIN)
00200		BEGIN ARRYIN
00300	
00400		PUSHJ	P,SAVE
00500		MOVE	LPSA,X44
00600	 	VALCHN	1,-3(P),WERR
00700		SETZEOF					;ASSUME OK
00800	DOSIMIO:
00900		SIMIO	2,TABL,WERR			;MOVE	6,-2(P)
01000		SKIPGE	2,-1(P)				;EXTENT
01100		  ERR	<ARRYIN:  Negative word count>
01200	WIN3:	JUMPE	2,RESTR				;NOTHING LEFT TO TRANSFER
01300		SKIPG	E,IOCNT(CDB)
01400		  JRST	WIN5
01500		IBP	IOBP(CDB)			;INCREMENT THE POINTER
01600		HRL	C,IOBP(CDB)			;SOURCE
01700		MOVEI	D,(6)				;FOR BLT
01800		HRR	C,6				;"TO" ADDRESS
01900		CAIG	B,(E)				;ENOUGH HERE
02000		  JRST	WIN4
02100		ADDI	D,-1(E)				;FINISH HERE
02200		BLT	C,(D)
02300		SUBM	E,IOCNT(CDB)
02400		ADDM	E,IOBP(CDB)
02500		ADD	6,E				;FIX INPUT POINTER
02600		SUB	B,E				;FIX INPUT COUNT
02700	WIN5:	PUSHJ	P,ADWI				;GET MORE
02800		  JRST	ISEOF				;END OF FILE -- NO MORE THERE
02900		JRST	WIN3
03000	WIN4:	ADDI	D,-1(B)				;
03100		BLT	C,(D)				;LAST BLT
03200		SUB	E,B				;FIX UP COUNT
03300		SOJ	B,
03400		MOVEM	E,IOCNT(CDB)
03500		ADDM	B,IOBP(CDB)
03600		JRST	RESTR
03700	
03800	TABL:	JRST	DOSETWI				;0 -- SET UP
03900		JRST	.CISWI				;1 -- XICHAR
04000		JRST	.COSWI				;2 -- XOCHAR
04100		MOVE	6,-2(P)				;3 -- XIWORD
04200		JRST	.WOSWI				;4 -- XOWORD
04300		JRST	WERR				;5 -- XCICHAR
04400		JRST	WERR				;6 -- XCOCHAR
04500		JRST	DOSIN				;7 -- XCWORD
04600		JRST	WERR				;10 -- XBYTE7
04700		JRST	WERR				;11 -- XDICHAR
04800		JRST	WERR				;12 -- XDOCHAR
04900		JRST	DODUMPI				;13 -- XDARR
05000	
05100	ISEOF:	MOVE	TEMP,-1(P)			;NUMBER OF WORDS WANTED
05200		SUBM	TEMP,B				;INPUT IN RH
05300	WIN2:	HRROM	B,.SKIP.
05400		SKIPE	ENDFL(CDB)
05500		  HRROM	B,@ENDFL(CDB)
05600		JRST	RESTR
05700	
05800	.CISWI:	PUSHJ	P,CISWI
05900		JRST	DOSIMIO
06000	
06100	.COSWI:	PUSHJ	P,COSWI
06200		JRST	DOSIMIO
06300	
06400	.WOSWI:	PUSHJ	P,WOSWI
06500		JRST	DOSIMIO
06600	
06700	DOSETWI:
06800		PUSHJ	P,SETWI
06900		JRST	DOSIMIO
07000	
07100	DOSIN:
07200		MOVN	3,-1(P)				;WORD COUNT	
07300		MOVSI	2,444400
07400		HRR	2,-2(P)				;ADDRESS OF BUFFER
07500		JSYS	SIN
07600		JUMPE	3,RESTR				;DID WE GET IT ALL?
07700	SINEOF:	ADD	3,-1(P)				;CALCULATE NO OF WORDS READ
07800		HRLI	3,-1				;MAKE IT XWD -1,,COUNT
07900		SKIPE	ENDFL(CDB)			;EOF LOCATION?
08000		  MOVEM	3,@ENDFL(CDB)			;YES
08100		MOVEM	3,.SKIP.
08200		JRST	RESTR				;AND RETURN
08300	
08400	DODUMPI:
08500		MOVN	3,-1(P)
08600		MOVEI	2,3
08700		HRL	3,3
08800		HRR	3,-2(P)				;ADDRESS OF BUFFER
08900		SUBI	3,1
09000		SETZ	4,				;END OF DUMP MODE COMMAND LIST
09100		JSYS	DUMPI				;DO IT
09200		  JRST	DMPERR
09300		JRST	RESTR				;ALL OK
09400	
09500	DMPERR:	CAIN	1,600220			;EOF?
09600		  JRST	DUMPEOF				;NO
09700		ERR	<ARRYIN:  Dump mode error>,1
09800		MOVEM	1,.SKIP.
09900		JRST	RESTR
10000	
10100	DUMPEOF:
10200		MOVE	1,DVTYP(CDB)
10300		CAIE	1,2				;MAGTAPE DEVICE?
10400		  JRST	INPEOF				;NO JUST INDICATE EOF
10500		HRRZ	1,JFNTBL(CHNL)	
10600		SETZ	2,				;MTOPR RESET
10700		JSYS	MTOPR	
10800		JRST	INPEOF				;INDICATE EOF AND RETURN
10900	
11000	WERR:	ERR	<ARRYIN:  Illegal JFN, byte-size, or mode.>,1
11100		JRST	INPEOF
11200	
11300	
11400		BEND ARRYIN
     

00100	HERE(WORDOUT)
00200		BEGIN WORDOUT
00300		PUSHJ	P,SAVE
00400		MOVE	LPSA,X33
00500		VALCHN	1,-2(P),WERR
00600		SETZEOF
00700	DOSIMIO:SIMIO	2,TABL,WERR			;SOSGE IOCNT(CDB)
00800		  JRST	.ADWO
00900		MOVE	2,-1(P)
01000		IDPB	2,IOBP(CDB)
01100		JRST	RESTR
01200	
01300	TABL:	JRST	DOSETWO				;0 -- XNULL
01400		JRST	.CISWO				;1 -- XICHAR
01500		JRST	.COSWO				;2 -- XOCHAR
01600		JRST	.WISWO				;3 -- XIWORD
01700		SOSGE	IOCNT(CDB)			;4 -- XOWORD
01800		JRST	WERR				;5 -- XCICHAR
01900		JRST	WERR				;6 -- XCOCHAR
02000		JRST	DOBOUT				;7 -- XCWORD
02100		REPEAT 4,<JRST WERR>			;10-13
02200	
02300	.ADWO:	PUSHJ	P,ADWO
02400		JRST	DOSIMIO
02500	
02600	DOSETWO:
02700		PUSHJ	P,SETWO
02800		JRST	DOSIMIO
02900	
03000	.CISWO:	PUSHJ	P,CISWO
03100		JRST	DOSIMIO
03200	
03300	.COSWO:	PUSHJ	P,COSWO
03400		JRST	DOSIMIO
03500	
03600	.WISWO:	PUSHJ	P,WISWO
03700		JRST	DOSIMIO
03800	
03900	WERR:	ERR	<WORDOUT:  Illegal JFN, byte-size, mode, or combination>,1
04000		JRST	INPEOF				;AND INDICATE ERROR
04100	
04200	DOBOUT:	MOVE	2,-1(P)
04300		JSYS	BOUT
04400		JRST	RESTR
04500	
04600		BEND WORDOUT
     

00100	HERE(ARRYOUT)
00200		BEGIN ARRYOUT
00300	
00400		PUSHJ	P,SAVE
00500		MOVE	LPSA,X44
00600		VALCHN	1,-3(P),WERR
00700		SKIPN	3,-1(P)
00800		  JRST	RESTR				;NOTHING TO MOVE
00900		JUMPGE	3,.+2
01000		   JRST	WERR
01100		SETZEOF
01200	DOSIMIO:SIMIO	2,TABL				;MOVE	6-2(P)
01300		SKIPGE	B,-1(P)
01400		  ERR	<ARRYOUT:  Word count is negative>,1
01500	WOUT2:	SKIPG	E,IOCNT(CDB)
01600		  JRST	WOUT5
01700		JUMPE	B,RESTR				;NOTHING LEFT
01800		IBP	IOBP(CDB)
01900		MOVE	C,IOBP(CDB)			;TO ADDR
02000		HRRZI	D,(C)				;FOR BLT TERMINATION
02100		HRLI	C,(6)
02200		CAIGE	B,(E)				;ENOUGHT IN BUFFER
02300		  JRST	WOUT3				;YES
02400		ADDI	D,-1(E)				;FINAL ADDRESS
02500		BLT	C,(D)
02600		ADDI	6,(E)				;UPDATE BP
02700		SUBI	B,(E)	
02800		SETZM	IOCNT(CDB)
02900		HRRM	D,IOBP(CDB)
03000	WOUT5:	PUSHJ	P,ADWO
03100		JRST	WOUT2
03200	WOUT3:	JUMPLE	B,RESTR
03300		SOJ	B,
03400		ADD	D,B
03500		BLT	C,(D)
03600		SUBI	E,1(B)
03700		MOVEM	E,IOCNT(CDB)
03800		ADDM	B,IOBP(CDB)
03900		JRST	RESTR
04000	
04100	TABL:	JRST	DOSETWO				;0 -- XNULL
04200		JRST	.CISWO				;1 -- XICHAR
04300		JRST	.COSWO				;2 -- XOCHAR
04400		JRST	.WISWO				;3 -- XIWORD
04500		MOVE	6,-2(P)				;4 -- XOWORD
04600		JRST	WERR				;5 -- XCICHAR
04700		JRST	WERR				;6 -- XCOCHAR
04800		JRST	DOSOUT				;7 -- XBYTE36
04900		JRST	WERR				;10 -- XBYTE7
05000		JRST	WERR				;11 -- XDICHAR
05100		JRST	WERR				;12 -- XDOCHAR
05200		JRST	DODUMPO				;13 -- XDARR
05300	
05400	DOSETWO:
05500		PUSHJ	P,SETWO
05600		JRST	DOSIMIO
05700	
05800	.CISWO:	PUSHJ	P,CISWO
05900		JRST	DOSIMIO
06000	
06100	.COSWO:	PUSHJ	P,COSWO
06200		JRST	DOSIMIO
06300	
06400	.WISWO:	PUSHJ	P,WISWO
06500		JRST	DOSIMIO
06600	
06700	DOSOUT:	
06800		MOVN	3,-1(P)
06900		MOVSI	2,444400
07000		HRR	2,-2(P)
07100		JSYS	SOUT
07200		JRST	RESTR
07300		
07400	DODUMPO:
07500		MOVN	3,-1(P)
07600		MOVEI	2,3
07700		HRL	3,3
07800		HRR	3,-2(P)
07900		SUBI	3,1
08000		SETZ	4,
08100		JSYS	DUMPO
08200		  JRST	DMPERR
08300	    	SETOM	DMPED(CDB)			
08400		JRST	RESTR
08500	
08600	WERR:	ERR	<ARRYOUT:  Illegal JFN, byte-size, mode, or combination.>,1
08700		JRST	INPEOF
08800	
08900	
09000	DMPERR:	ERR	<ARRYOUT:  Dump mode error>,1
09100		MOVEM	1,.SKIP.			;SAVE TENEX ERROR NUMBER
09200		JRST	RESTR
09300	
09400	
09500		BEND ARRYOUT
     

00100	
00200	HERE(RWDPTR)
00300		BEGIN RWDPTR
00400	
00500		PUSHJ	P,SAVE
00600		MOVE	LPSA,X22
00700		VALCHN	1,-1(P),WERR
00800		SETZM	.SKIP.
00900	DOSIMIO:SIMIO	2,TABL,WERR			;PUSHJ P,GETWPT
01000	STOAC2:	MOVEM	2,RACS+A(USER)
01100		JRST	RESTR
01200	
01300	TABL:	JRST	RNULL				;0 -- XNULL
01400		PUSHJ	P,GETWPT			;1 -- XICHAR
01500		PUSHJ 	P,GETWPT			;2 -- XOCHAR	
01600		PUSHJ	P,GETWPT			;3 -- XIWORD
01700		PUSHJ	P,GETWPT			;4 -- XOWORD
01800		JRST	WERR				;5 -- XCICHAR
01900		JRST	WERR				;6 -- XCOCHAR
02000		JRST	DORFPTR				;7 -- XCWORD
02100		REPEAT 4,<JRST WERR>			;10-13
02200	
02300	DORFPTR:
02400		JSYS	RFPTR
02500		   JRST .+2
02600		JRST	STOAC2
02700		ERR	<RWDPTR:  Cannot do RFPTR.>,1
02800		MOVEM	1,.SKIP.
02900		JRST	RNULL
03000	WERR:	ERR	<RWDPTR:  Illegal JFN, illegal mode or byte size.>,1
03100		SETOM	.SKIP.
03200	
03300	RNULL:	
03400		PUSHJ	P,SETWIO
03500		JRST	DOSIMIO				;AND LOOK AGAIN
03600	
03700	
03800		BEND RWDPTR
     

00100	HERE(SWDPTR)
00200		BEGIN SWDPTR
00300		
00400		PUSHJ	P,SAVE
00500		MOVE	LPSA,X33
00600		VALCHN	1,-2(P),WERR	
00700		SETZM	.SKIP.
00800	DOSIMIO:MOVE	2,-1(P)				;PICK UP NEW WORD IN 2
00900		SIMIO	3,TABL,WERR
01000		JRST	RESTR
01100	
01200	TABL:	JRST 	RNULL				;0 -- XNULL
01300		PUSHJ	P,SETWPT			;1 -- XICHAR
01400		PUSHJ	P,SETWPT			;2 -- XOCHAR	
01500		PUSHJ	P,SETWPT			;3 -- XIWORD
01600		PUSHJ	P,SETWPT			;4 -- XOWORD
01700		JRST	WERR				;5 -- XCICHAR
01800		JRST 	WERR				;6 -- XCOCHAR
01900		JRST	DOSFPTR				;7 -- XCWORD
02000		REPEAT	4,<JRST	WERR>			;10-13
02100	
02200	DOSFPTR:JSYS	SFPTR
02300		  JRST	SFERR
02400		JRST	RESTR
02500	
02600	SFERR:	ERR	<SWDPTR:  Cannot do SFPTR>,1
02700		MOVEM	1,.SKIP.
02800		JRST	RESTR
02900	
03000	WERR:	ERR	<SWDPTR:  Illegal JFN, byte size, or mode.>,1
03100		SETOM	.SKIP.
03200		JRST	RESTR
03300	
03400	RNULL:	PUSHJ	P,SETWIO
03500		JRST	DOSIMIO
03600	
03700		BEND SWDPTR
     

00100	
00200	DSCR
00300		Some auxiliary routines, mostly for word i/o.
00400	⊗
00500	INPEOF:
00600	;HERE IF WE HAVE HIT EOF ON INPUT AND WISH TO SIMPLY SAY SO AND RETURN
00700		SETOEOF
00800		JRST	RESTR
00900	
01000	;ROUTINES TO SET TO WORD OUTPUT
01100	COSWO:	PUSHJ	P,CHCEOF			;CHECK FOR NEW CHARACTER EOF
01200	CISWO:
01300	WISWO:
01400		PUSHJ	P,GTWPT1
01500		MOVEM	3,IOBP(CDB)
01600		MOVEM	4,IOCNT(CDB)
01700		MOVEI	3,XOWORD
01800		MOVEM	3,IOSTT(CDB)
01900		POPJ	P,
02000	
02100	;ROUTINES TO SET TO CHARACTER OUTPUT
02200	WOSCO:	PUSHJ	P,CHWEOF			;CHECK FOR NEW WORD EOF
02300	CISCO:
02400	WISCO:
02500		PUSHJ	P,GTCPT1
02600		MOVEM	3,IOBP(CDB)
02700		MOVEM	4,IOCNT(CDB)
02800		MOVEI	3,XOCHAR
02900		MOVEM	3,IOSTT(CDB)
03000		POPJ	P,
03100	
03200	
03300	;ROUTINES TO SET TO CHARACTER INPUT
03400	WOSCI:	PUSHJ	P,CHWEOF			;CHECK FOR NEW WORD EOF
03500		JRST	.+2	
03600	COSCI:	PUSHJ	P,CHCEOF			;CHECK FOR NEW CHARACTER EOF
03700	WISCI:	PUSHJ	P,GTCPT1
03800		MOVEM	3,IOBP(CDB)
03900		MOVEM	5,IOCNT(CDB)
04000		MOVEI	3,XICHAR
04100		MOVEM	3,IOSTT(CDB)
04200		POPJ	P,
04300	
04400	;ROUTINES TO SET TO WORD INPUT
04500	COSWI:	PUSHJ	P,CHCEOF			;CHECK FOR NEW CHARACTER EOF
04600		JRST	.+2
04700	WOSWI:	PUSHJ	P,CHWEOF			;CHECK FOR NEW WORD EOF
04800	CISWI:	PUSHJ	P,GTWPT1
04900		MOVEM	3,IOBP(CDB)
05000		MOVEM	5,IOCNT(CDB)
05100		MOVEI	3,XIWORD
05200		MOVEM	3,IOSTT(CDB)
05300		POPJ	P,
05400	
05500	
05600	SETWND:
05700	;1, CDB LOADED
05800	;SETS THE FDB SO THAT THE BYTE SIZE IS 36 AND THE NUMBER OF BYTES IS AS IN 2
05900		PUSH	P,2				;SAVE 
06000		PUSH	P,3
06100		MOVEM	2,FDBEOF(CDB)
06200		HRLI	1,12				;OFFSET FOR
06300		MOVEM	2,3				;NUMBER OF WORDS
06400		SETO	2,				;BYTE MASK
06500		JSYS	CHFDB				;CHANGE THE EOF POINTER
06600		MOVEI	2,=36
06700		MOVEM	2,FDBSZ(CDB)
06800		HRLI	1,11				;OFFSET FOR BYTE SIZE
06900		MOVSI	2,007700			;MASK
07000		MOVSI	3,004400			;36 BIT BYTES
07100		JSYS	CHFDB
07200		HRLI	1,0				;RESTORE GOOD JFN IN 1
07300		POP	P,3				;RESTORE
07400		POP	P,2
07500		POPJ	P,				;AND RETURN
07600	
07700	
07800	GETWND:
07900	;HERE WITH 1,CDB LOADED
08000	;RETURN THE WORD THAT ADDRESSES EOF IN 2, ACCORDING TO THE SYSTEM
08100		BEGIN GETWND
08200		PUSH	P,3
08300		SKIPN	3,FDBSZ(CDB)			;IF BYTE SIZE IS ZERO
08400		  JRST	RET0				;THEN RETURN 0
08500		CAIN	3,=36				;ALREADY 36?
08600		  JRST	RET1				;RETURN WHAT WE ALREADY HAVE THERE
08700	;THE BYTE SIZE OF A FILE CAN BE 0 TO =64.  0 IS ALREADY TAKEN CARE OF ABOVE
08800		CAILE	3,=36	
08900		  ERR	<GETWND:  File byte size is bigger than 36 bits>,1
09000		MOVEI	2,=36
09100		IDIVI	2,(3)				;NUMBER TO MULTIPLY BY -- CLOBBERS 3!!
09200		MOVEM	2,3
09300		MOVE	2,FDBEOF(CDB)
09400		IDIVI	2,(3)				;NUMBER OF WORDS -- CLOBBERS 3!!
09500		JUMPE	3,.+2				;EXTRA WORDS?
09600		  AOJ	2,				;YES.
09700	POPBACK:POP	P,3
09800		POPJ	P,
09900	
10000	RET0:	SETZ	2,
10100		JRST	POPBACK
10200	
10300	RET1:	MOVE	2,FDBEOF(CDB)
10400		JRST	POPBACK
10500	
10600		BEND GETWND
10700	
10800	GETWPT:	
10900	;HERE WITH 1,CDB LOADED
11000	;RETURNS IN 2 THE WORD THAT ADDRESSES EOB
11100		BEGIN GETWPT
11200		SKIPN	2,IOBP(CDB)
11300		  POPJ	P,				;WORD ZERO
11400		PUSH	P,3
11500		TLZ	2,007700
11600		TLO	2,004400			;MAKE 36 BIT
11700		IBP	2
11800		MOVE	3,IOADDR(CDB)	
11900		SUBI	3,(2)
12000		MOVE	2,IOPAGE(CDB)			;CURRENT PAGE
12100		LSH	2,9				;NUMBER OF WORDS IN PREVIOUS PAGES
12200		SUB	2,3				;SUBTRACT SINCE 3 IS NEGATIVE
12300		POP	P,3				;RESULT IN 2
12400		POPJ	P,
12500	
12600		BEND GETWPT
12700	
12800	GTWPT1:
12900	;HERE WITH 1,CHNL,CDB LOADED
13000	;RETURN IN 2 THE WORD THAT ADDRESSES EOB IN 2, ACCORDING TO THE CURRENT POINTER
13100	;RETURN IN 3 THE UPDATED BYTE POINTER
13200	;RETURN IN 4 THE COUNT REMAINING FOR OUTPUT
13300	;RETURN IN 5 THE COUNT REMAINING FOR INPUT
13400		BEGIN GTWPT1
13500		SKIPN	3,IOBP(CDB)	
13600		  JRST	NULRET
13700		TLZ	3,007700
13800		TLO	3,004400			;MAKE A 36-BIT BP	
13900		MOVEM	3,2				;COPY INTO 2
14000		IBP	2
14100		MOVE	4,IOADDR(CDB)			;START OF BUFFER
14200		SUBI	4,(2)				;NUMBER OF WORDS CURRENTLY COMMITTED TO
14300							;IN THIS BUFFER
14400		MOVE	2,IOPAGE(CDB)			;WHERE THE CURRENT IO IS
14500		LSH	2,9
14600		SUB	2,4				;NUMBER OF WORDS TO ADDRESS EOF
14700		ADDI	4,1000				;NUMBER OF WORDS REMAINING IN  THIS BUFFER
14800							;FOR OUTPUT PURPOSES
14900		MOVEM	2,5				;SAVE CURRENT EOB POINTER
15000		PUSHJ	P,GETWND			;READ THE END OF FILE IN FDB
15100	 	EXCH	5,2				;EOB POINTER TO 2, EOF TO 5
15200		SUB	5,2				;SUBTRACT THE CURRENT EOB POINTER
15300		CAML	5,4				;IF LESS THAN OUTPUT COUNT THEN USE IT ELSE
15400		  MOVEM	4,5				;USE OUTPUT COUNT
15500		POPJ	P,
15600	
15700	NULRET:	SETZB	2,3				;EVERYTHING ZERO
15800		SETZB	4,5
15900		POPJ	P,
16000	
16100	
16200		BEND GTWPT1
16300	
16400	CHWEOF:
16500	;1,CDB LOADED
16600	;SEES IF A CHANGE OF EOF IS NEEDED, AND DOES IT
16700		SKIPN	IOBP(CDB)			;ANYTHING THERE?
16800		  POPJ	P,				;NO, DONT FIDDLE AROUND
16900		PUSH	P,2
17000		PUSH	P,3
17100		PUSHJ	P,GETWND			;GET WORD EOF
17200		MOVEM	2,3				;SAVE IN 6
17300		PUSHJ	P,GETWPT			;GET WORD EOB
17400		CAML	2,3				;IS EOB LESS THAN EOF?
17500		  PUSHJ	P,SETWND			;BETTER RESET FDB -- ALSO IF TEST IS EQUAL	   
17600		POP	P,3
17700		POP	P,2
17800		POPJ	P,
17900	
18000	
     

00100	SETWPT:
00200		BEGIN SETWPT
00300	;HERE WITH 1,CDB LOADED
00400	;2 HAS THE WORD THAT WE WANT TO SET TO
00500		MOVE	3,IOSTT(CDB)
00600		CAIN	3,XOWORD			;DOING WORD OUTPUT?
00700		  PUSHJ	P,CHWEOF			;YES CHECK
00800		CAIN	3,XOCHAR			;DOING CHAR OUTPUT?
00900		  PUSHJ	P,CHCEOF			;CHECK IT ALSO
01000		CAMN	2,[-1]				;WANT EOF?
01100		  PUSHJ	P,GETWND			;YES
01200		PUSH	P,2				;SAVE ON STACK
01300		LSH	2,-9
01400		CAME	2,IOPAGE(CDB)			;SAME PAGE?
01500		  PUSHJ	P,SETPAGE			;NO, SET THE PAGE
01600		POP	P,2	
01700		ANDI	2,777				;PICK UP WORD IN PAGE
01800		MOVE	3,IOADDR(CDB)
01900		ADDI	3,(2)
02000		HRLI	3,444400			;MAKE A BYTE POINTER
02100		MOVEM	3,IOBP(CDB)
02200		MOVE	3,IOSTT(CDB)			;CHECK THE STATUS AT THE MOMENT	
02300		CAIE	3,XICHAR			;IF INPUTTING CHARS
02400		CAIN	3,XIWORD			;OR WORDS
02500		  JRST	ASSUMIN				;THEN ASSUME WE WILL CONTINUE TO INPUT
02600		MOVEI	3,XOWORD			;WELL ASSUME OUTPUT
02700		MOVEM	3,IOSTT(CDB)
02800	FULBU1:	MOVEI	3,1000				;OTHERWISE ASSUME OUTPUT
02900		SUBI	3,(2)
03000	STOAC3:	MOVEM	3,IOCNT(CDB)
03100		POPJ	P,
03200	ASSUMIN:
03300		MOVEI	3,XIWORD
03400		MOVEM	3,IOSTT(CDB)
03500		PUSH	P,2				;SAVE THE NUMBER OF WORDS
03600		PUSHJ	P,GETWND			;GET THE END OF THE FILE IN WORDS IN 2
03700		IDIVI	2,1000				;PAGES IN 2, WORDS IN 3	
03800		CAMGE	2,IOPAGE(CDB)			;IS REQUESTED PAGE BEYOND EOF?
03900		  JRST	EMPBUF				;YES
04000		CAME	2,IOPAGE(CDB)			;SOMEWHERE ON THIS PAGE?
04100		  JRST	FULBUF				;NO
04200		POP	P,2
04300		SUB	3,2
04400		JRST	STOAC3
04500	
04600	FULBUF:	POP	P,2
04700		JRST	FULBU1
04800	
04900	EMPBUF:	POP	P,2
05000		SETZ	3,				;SAY EMPTY
05100		JRST	STOAC3
05200		BEND SETWPT
05300	
05400	SETPAGE:
05500	;1,CDB,CHNL LOADED
05600	;2 HAS THE NUMBER OF THE PAGE WE WANT MAPPED
05700		PUSH	P,1				;SAVE JFN
05800		PUSH	P,2
05900		PUSH	P,3
06000		MOVEM	2,IOPAGE(CDB)			;PAGE BEING INSERTED
06100		PUSH	P,1				;SAVE JFN OVER SFPTR
06200		LSH	2,9				;MAKE INTO WORDS
06300		JSYS	SFPTR
06400		  ERR	<SETPAGE:  Cannot do SFPTR>,1
06500		POP	P,1
06600		HRL	1,1
06700		HRR	1,IOPAGE(CDB)			;XWD JFN,FILEPAGE
06800		HRLZI	3,140000			;BITS 2 AND 3 FOR READ, WRITE -- ASSUME THIS
06900		MOVE	2,OFL(CDB)			;BUT BETTER CHECK:
07000		TESTN	2,WRBIT				;IF WRITING OR
07100		TESTE	2,APPBIT			;APPENDING
07200		  JRST	.+2				;THEN DONT DO
07300		TESTO	3,1B9				;THE COPY ON WRITE -- DO IT FOR READING THOUGH
07400		MOVE	2,FKPAGE(CDB)			;BUFFER IN CORE
07500		JSYS	PMAP
07600		POP	P,3
07700		POP	P,2
07800		POP	P,1				;RESTORE THE JFN
07900		POPJ	P,
08000	
     

00100	SETWIO:
00200	;1,CDB LOADED
00300	;DECIDE WHETHER TO SETWI OR SETWO
00400	;CLOBBERS 2,3
00500		MOVEI	3,SETWI				;ASSUME WORD INPUT
00600		MOVE	2,OFL(CDB)
00700		TESTN	2,RDBIT				;DOING INPUT
00800		  MOVEI	3,SETWO				;NOPE ASSUME OUTPUT
00900		JRST	(3)				;AND POPJ BACK
     

00100	ADWI:	
00200	;1,CDB LOADED
00300	;CALL PUSHJ
00400	;RETURN:
00500	;	+1 FOR EOF
00600	;	+2 FOR NORMAL
00700	;ADVANCES WORD INPUT FROM DSK
00800		BEGIN ADWI
00900	
01000		PUSH	P,2
01100		PUSH	P,3
01200		MOVE	3,IOPAGE(CDB)			;CURRENT PAGE
01300		AOJ	3,				;NEXT PAGE
01400		LSH	3,9				;WORDS IN THAT PAGE
01500		PUSHJ	P,GETWND			;END OF FILE POINTER
01600		CAML	3,2				;BEYOND
01700		  JRST	ADEOF				;YES SAY SO
01800		SUB	2,3	
01900		CAILE	2,1000				;LESS THAN A FULL BUFFER?
02000		  MOVEI	2,1000				;NO GIVE ENTIRE AMOUNT
02100		MOVEM	2,IOCNT(CDB)
02200		AOS	2,IOPAGE(CDB)			;INCREMEMT PAGE, GET IN 2
02300		PUSHJ	P,SETPAGE	
02400		MOVE	2,IOADDR(CDB)
02500		HRLI	2,444400
02600		MOVEM	2,IOBP(CDB)
02700	ADRET:	AOS	-2(P)
02800	ADEOF:	POP	P,3
02900		POP	P,2
03000		POPJ	P,
03100	
03200		BEND ADWI
03300	
03400	ADWO:
03500	;1,CDB LOADED
03600	;ADVANCES WORD OUTPUT FROM DSK
03700		BEGIN ADWO
03800	
03900		PUSH	P,2
04000		AOS	2,IOPAGE(CDB)			;NEXT PAGE OF THE FILE
04100		PUSHJ	P,SETPAGE
04200	 	MOVEI	2,1000
04300		MOVEM	2,IOCNT(CDB)	
04400		MOVE	2,IOADDR(CDB)	
04500		HRLI	2,444400
04600		MOVEM	2,IOBP(CDB)
04700		POP	P,2
04800		POPJ	P,
04900	
05000		BEND ADWO
     

00100	DSCR  CHAR←CHARIN(CHANNEL)
00200	⊗
00300	HERE(CHARIN)
00400		BEGIN CHARIN
00500	
00600		PUSHJ	P,SAVE
00700		MOVE	LPSA,X22
00800		LITCHN	1,-1(P),CHALIT
00900		SETZEOF
01000	DOSIMIO:	
01100		SIMIO	E,TABL,CERR			;SOSGE IOCNT(CDB)
01200		  JRST	.DOINP
01300		ILDB	2,IOBP(CDB)
01400	STOAC2:	MOVEM	2,RACS+A(USER)
01500		JRST	RESTR
01600	
01700	TABL:	JRST	DOSETCI				;0 -- XNULL
01800		SOSGE	IOCNT(CDB)			;1 -- XICHAR
01900		JRST	.COSCI				;2 -- XOCHAR
02000		JRST	.WISCI				;3 -- XIWORD
02100		JRST	.WOSCI				;4 -- XOWORD
02200		SOSGE	IOCNT(CDB)			;5 -- XCICHAR
02300		REPEAT 2,<JRST CERR>			;6,7 -- XCOCHAR,XCOWORD
02400		SOSGE	IOCNT(CDB)			;10 -- XBYTE7
02500		SOSGE	IOCNT(CDB)			;11 -- XDICHAR
02600		REPEAT 2,<JRST CERR>			;12,13 -- XDOCHAR,XDARR
02700	
02800	.DOINP:
02900		PUSHJ	P,DOINP				;READ NEXT BUFFER
03000		JRST	DOSIMIO				;BUFFERED INPUT RETURN
03100		JRST	IND				;CHARACTER IN D--DID A BIN
03200		JRST	ADCIEOF				;EOF
03300	
03400	ADCIEOF:SETZM	RACS+A(USER)			;RETURN 0
03500		JRST	INPEOF				;AND SAY EOF
03600	DOSETCI:
03700		PUSHJ	P,SETCI
03800		JRST	DOSIMIO
03900	
04000	
04100	.COSCI:	PUSHJ	P,COSCI
04200		JRST	DOSIMIO
04300	
04400	.WISCI:	PUSHJ	P,WISCI
04500		JRST	DOSIMIO
04600	
04700	.WOSCI:	PUSHJ	P,WOSCI
04800		JRST	DOSIMIO
04900	
05000	CERR:	ERR	<CHARIN:  Illegal JFN, byte-size, or mode>,1
05100		JRST	INPEOF				;INDICATE EOF AND RETURN
05200	
05300	CHALIT:	SETZM	.SKIP.
05400		MOVE	1,-1(P)				;PICK UP JFN LITERALLY
05500		JSYS	BIN
05600		JUMPN	2,STOAC2
05700		SETZM	RACS+A(USER)
05800		JSYS	GTSTS
05900		TESTE	2,1B8
06000		  SETOM	.SKIP.
06100		JRST	RESTR
06200	
06300	IND:	MOVEM	D,2				;PUT IN 2
06400		JRST	STOAC2				;AND RETURN CHARACTER
06500	
06600		BEND CHARIN
     

00100	DSCR STRING SIMPLE PROCEDURE SINI(INTEGER JFN,MAXLENGTH,BRKCHAR);
00200		Reads in a string of characters, terminated by BRKCHAR or	
00300	reaching maxlength, whichever happens first.
00400	⊗
00500	
00600	HERE(SINI)
00700		BEGIN	SINI
00800	
00900		PUSHJ	P,SAVE
01000		MOVE	LPSA,X44
01100		VALCHN	1,-3(P),CERR
01200		SETZEOF
01300	DOSIMIO:SKIPG	C,-2(P)
01400		  JRST	NULRET
01500		SIMIO	2,TABL,CERR		;EXCH	1,C
01600		SKIPE	SGLIGN(USER)	
01700		  PUSHJ	P,INSET
01800		ADDM	1,REMCHR(USER)		
01900		SKIPLE	REMCHR(USER)
02000		  PUSHJ	P,STRNGC
02100		MOVE	E,TOPBYTE(USER)		;BYTE POINTER TO TOP OF STRING SPACE
02200		PUSH	SP,[0]
02300		PUSH	SP,E
02400		EXCH	1,C			;1 HAS JFN, C HAS COUNT
02500		MOVN	C,C
02600	IN1:	SOSGE	IOCNT(CDB)
02700		  JRST	.DOINP
02800	IN2:	ILDB	D,IOBP(CDB)
02900	IND:	JUMPE	D,IN1			;IF EMPTY KEEP LOOKING
03000		CAMN	D,-1(P)			;BREAK CHAR?
03100		  JRST	DOBRK			;YES
03200		IDPB	D,E
03300	IN3:	AOJL	C,IN1			;SUBTRACT 1 AND JUMP IF GREATER
03400	
03500		SETOM	.SKIP.			;INDICATE TERMINATED FOR COUNT
03600	DONE:	ADDM	C,REMCHR(USER)		;MAKE REMCHR HONEST
03700		MOVEM	E,TOPBYTE(USER)
03800		ADD	C,-2(P)			;GET ACTUAL NUMBER OF CHARACTERS 
03900						;TRANSFERRED	
04000		HRROM	C,-1(SP)		;SAVE COUNT FOR USER
04100		JRST	RESTR
04200	
04300	DOBRK:	IDPB	D,E			;SAVE THE BREAK CHARACTER (AS DOES THE SIN JSYS)
04400		MOVEM	D,.SKIP.		;SAVE BREAK CHARACTER IN .SKIP. AS DOC. SAYS
04500		AOJ	C,			;ADD 1 TO THE COUNT
04600		JRST 	DONE			;AND FINISH UP
04700	
04800	CERR:	ERR <SINI:  Illegal JFN, illegal mode or byte size>,1
04900	NULRET:	PUSH	SP,[0]			;RETURN NULL STRING
05000		PUSH	SP,[0]
05100		JRST	RESTR
05200		
05300	TABL:	JRST	DOSETCI			;0 -- XNULL
05400		EXCH	1,C			;1 -- XICHAR
05500		JRST	.COSCI			;2 -- XOCHAR
05600		JRST	.WISCI			;3 -- XIWORD
05700		JRST	.WOSCI			;4 -- XOWORD		
05800		EXCH	1,C			;5 -- XCICHAR
05900		JRST	CERR			;6 -- XCOCHAR
06000		JRST	CERR			;7 -- XCWORD
06100		EXCH	1,C			;10 -- XBYTE7
06200		EXCH	1,C			;11 -- XDICHAR
06300		REPEAT 2,<JRST CERR>		;12,13 -- XDOCHAR,XDARR
06400	
06500	.DOINP:	PUSHJ	P,DOINP			;READ IN THE NEXT BUFFER
06600		JRST	IN1			;GOT IT
06700		JRST	IND			;CHARACTER IN D
06800	DOEOF:	SETOEOF				;END OF FILE
06900		JRST	DONE
07000	
07100	DOSETCI:	
07200		PUSHJ	P,SETCI
07300		JRST	DOSIMIO
07400	
07500	.COSCI:	PUSHJ	P,COSCI
07600		JRST	DOSIMIO
07700	
07800	.WISCI:	PUSHJ	P,WISCI
07900		JRST	DOSIMIO
08000	
08100	.WOSCI:	PUSHJ	P,WOSCI
08200		JRST	DOSIMIO
08300	
08400	
08500		BEND SINI
08600	
     

00100	COMMENT ⊗Input ⊗
00200	
00300	DSCR  "STRING"←INPUT(CHANNEL,BREAK TABLE NUMBER);
00400	CAL SAIL
00500	SID NO ACS SAVED BY INPUT!!!!!!
00600	⊗
00700	
00800	.IN.:
00900	HERE (INPUT)	
01000		MOVE	USER,GOGTAB	;GET TABLE POINTER
01100	;;%##% FOR BENEFIT OF ERROR ROUTINE
01200		MOVE	TEMP,(P)
01300		MOVEM	TEMP,UUO1(USER)
01400	;;%##%
01500		MOVEM	RF,RACS+RF(USER);SAVE F-REGISTER
01600		SKIPE	SGLIGN(USER)
01700		PUSHJ	P,INSET
01800		
01900		VALCHN	1,-2(P),INPBAD	;MOSTLY EXTRA CODE REALLY
02000	INPSIM:
02100		SIMIO	E,INPTBL,INPBAD	;MOVE X,-1(P)  ; TABLE NUMBER
02200	
02300		MOVEI	TEMP,-1		;ERROR IF BLOCK NOT THERE OR TABLE NOT INIT'ED
02400		PUSHJ	P,BKTCHK	;CHECK TABLE #
02500		 JRST	[PUSH	SP,[0]	;ERROR
02600			PUSH	SP,[0]
02700			SUB	P,X33
02800			JRST	@3(P)]
02900		PUSH	P,CDB		;SAVE POINTER TO CORGET BLOCK
03000		PUSH	P,CHNL		;SAVE RANGE 1 TO 18
03100	
03200		MOVE	CHNL,-4(P)	;CHANNEL NUMBER -- ALREADY CHECKED
03300		MOVE	CDB,CDBTBL(CHNL)
03400		HRRZ	CHNL,JFNTBL(CHNL);ALREADY CHECKED ABOVE
03500	;;;;	LDB	E,[POINT 4,OFL(CDB),9] ;DATA MODE
03600		SETZEOF
03700		SKIPE	BRCHAR(CDB)	;BRCHAR LOCATION
03800		  SETZM	@BRCHAR(CDB)	;ASSUME NO BREAK CHAR
03900		MOVEI	A,=200		;DEFAULT NO. OF CHARS
04000		SKIPE	ICOUNT(CDB)	;USER-SPECIFIED COUNT?
04100		  HRRZ	A,@ICOUNT(CDB)	;MAX COUNT FOR INPUT STRING
04200		ADDM	A,REMCHR(USER)
04300		SKIPLE	REMCHR(USER)	;ENOUGH ROOM?
04400		PUSHJ	P,STRNGC	;NO, TRY TO GET SOME
04500	
04600		POP	P,TEMP
04700		MOVE	FF,BRKMSK(TEMP)	;BITS FOR THIS TABLE
04800		POP	P,LPSA		;LPSA POINTS AT CORGET BLOCK FOR BREAK TABLES
04900		ADD	TEMP,LPSA	;TEMP IS RELOCATED 1 TO 18
05000		MOVEM	TEMP,-1(P)	;SAVE RELOCATED 1 TO 18 ON STACK
05100		MOVEI	Z,1		;FOR TESTING LINE NUMBERS
05200		SKIPN	LINTBL(TEMP)	;DON'T LET TEST SUCCEED IF
05300		  MOVEI	 Z,0		;WE'RE TO LET LINE NUMBERS THRU
05400	
05500		MOVN	B,A		;NEGATE MAX CHAR COUNT
05600		PUSH	SP,[0]		;LEAVE ROOM FOR FIRST STR WORD
05700		PUSH	SP,TOPBYTE(USER)	;SECOND STRING WORD
05800		MOVE	Y,LPSA
05900		ADD	Y,[XWD D,BRKTBL] ;BRKTBL+RLC(LPSA)
06000		JUMPE	B,DONE1		; BECAUSE THE AOJL WON'T
06100	
06200	;;%DQ% JFR 8-17-76
06300		TRNE	FF,@BRKDUM(LPSA);TREAT NUL LIKE ORDINARY CITIZEN?
06400		TROA	C,1		;YES
06500		TRZ	C,1		;NO
06600	;;%DQ% ↑
06700		TRNE	FF,@BRKCVT(LPSA)	;DOING UC COERCION?
06800		TLOA	C,400000	;YES
06900		TLZ	C,400000	;NO
07000		
07100	.IN:	SOSGE	IOCNT(CDB)	;BUFFER EMPTY?
07200		 JRST	.DOINP
07300	IN1:	
07400		ILDB	D,IOBP(CDB)	;GET NEXT CHARACTER
07500	    	TDNE	Z,@IOBP(CDB)	;LINE NUMBER (ALWAYS SKIPS IF NOT WORRIED)?
07600		JRST	INLINN		;YES, GO SEE WHAT TO DO
07700	IN2:
07800	INB:
07900	;;%DQ% JFR 8-17-76
08000		JUMPE	D,[TRNN	C,1	;REALLY IGNORE 0'S ?
08100			   JRST	.IN	;YES
08200			   JRST	NOCV.I	];NO-- AND WE KNOW IT'S A 0, SO GET TO THE POINT
08300	;;%DQ% ↑
08400		CAILE	D,14		;FIRST CHECK
08500		  JRST	INB1		;IF IN RANGE AT ALL
08600		CAIN	D,12
08700		  JRST	INB2
08800		CAIE	D,14		;LF OR FF?
08900		  JRST	INB1		;NO
09000	INB2:	SKIPN	LINNUM(CDB)	;COUNTING VIA SETPL FUNCTION??
09100	 	  JRST	INB1		;NO
09200		TDNN	FF,@Y		;SOMETHING SPECIAL FOR THIS CHARACTER?
09300		  JRST	INCR		;NO NOTHING SPECIAL
09400		HLLZ	TEMP,@Y		;GET BITS FOR THIS CHAR
09500		TDNN	TEMP,FF		;IGNORE?
09600		  JRST	INCR		;YES
09700		MOVE	TEMP,-1(P)	;BREAKTABLE (RELOCATED)
09800		SKIPLE	DSPTBL(TEMP)	;APPEND OR SKIP?
09900		  JRST	INB1		;YES
10000	INCR:	CAIN	D,12		;LINE-FEED?
10100		  AOS	@LINNUM(CDB)	;INDICATE ANOTHER LINE
10200		CAIE	D,14		;FORM-FEED?
10300		  JRST	INB1		;NO
10400		SKIPE	PAGNUM(CDB)	
10500		 AOS	@PAGNUM(CDB)	;COUNT PAGES ALSO
10600		SKIPE	LINNUM(CDB)
10700		  SETZM @LINNUM(CDB)	;SET LINNUM TO ZERO (NEW PAGE)
10800	
10900	INB1:	JUMPGE	C,NOCV.I	;NOT COERCING?
11000		CAIL	D,"a"		;ONLY COERCE LOWER CASE
11100		CAILE	D,"z"		;
11200		JRST	.+2		;SPECIAL RHT "FAST SKIP"
11300		TRZ	D,40		;MAKE UPPER CASE
11400	
11500	NOCV.I:	TDNE	FF,@Y		;MUST WE DO SOMETHING SPECIAL?
11600		JRST	INSPC		;YES, HANDLE
11700	
11800	MOVEC:	IDPB	D,TOPBYTE(USER)	;LENGTHEN STRING
11900		AOJL	B,.IN		;GET SOME MORE
12000		JRST	DONE1
12100	
12200	INSPC:	HLLZ	TEMP,@Y		;IGNORE OR BREAK?
12300		TDNN	TEMP,FF		;  (CHOOSE ONE)
12400		JRST	.IN		;IGNORE
12500	
12600	;  BREAK -- STORE BREAK CHAR, FINISH OFF
12700	
12800	DONE:	SKIPE	BRCHAR(CDB)	;USER BRCHAR VAR?
12900		  MOVEM	D,@BRCHAR(CDB)	;STORE BREAK CHAR
13000		MOVE	TEMP,-1(P)	;RELOCATED 1 TO 18
13100		SKIPN	Y,DSPTBL(TEMP)	;WHAT TO DO WITH BREAK CHAR?
13200		JRST	DONE1		;SKIP IT
13300		JUMPL	Y,APPEND	;ADD TO END OF INPUT STRING
13400	
13500	RETAIN:	PUSHJ	P,BACKUP
13600		JRST	DONE1
13700	
13800	APPEND:	IDPB	D,TOPBYTE(USER)	;PUT ON END
13900		AOJA	B,DONE1		;ONE MORE TO COUNT
14000	
14100	
14200	;  DONE -- MARK STRING COUNT WORD
14300	
14400	DONE1:	ADDM	B,REMCHR(USER)	;GIVE UP THOSE NOT USED
14500		SKIPN	ICOUNT(CDB)	;USER SUPPLIED COUNT?
14600		  JRST	[ADDI B,=200	;USER DEFAULT
14700			 JRST .+2]
14800		ADD	B,@ICOUNT(CDB)	;HOW MANY DID WE ACTUALLY GET?
14900	;;#GI# DCS 2-5-72 REMOVE TOPSTR
15000		HRROM	B,-1(SP)	;MARK RESULT, NON-CONSTANT
15100	;;#GI#
15200		MOVE	RF,RACS+RF(USER);GET F-REGISTER BACK
15300		SUB	P,X33		;REMOVE INPUT PARAMETER, RETURN ADDRESS
15400		JRST	@3(P)		;RETURN
15500	
15600	;  CAN EITHER DELETE LINE NUMBER (Y GT 0) OR STOP,
15700	;  TELL THE USER (BRCHAR=-1), AND MARK LINE NUMBER
15800	;  NOT A LINE NUMBER FOR NEXT TIME
15900	
16000	
16100	
16200	
     

00100	.DOINP:	PUSHJ	P,DOINP
00200		JRST	.IN			;NORMAL BUFFERED RETURN
00300		JRST	INB			;7-BIT, CHAR IN D
00400		JRST	DONE1			;EOF OR ERROR
00500	
00600		BEGIN INPTBL
00700	
00800	↑INPTBL:JRST	DOSETCI			;0 -- XNULL
00900		MOVE	X,-1(P)			;1 -- XICHAR
01000		JRST	.COSCI			;2 -- XOCHAR
01100		JRST	.WISCI			;3 -- XIWORD
01200		JRST	.WOSCI			;4 -- XOWORD
01300		MOVE	X,-1(P)			;5 -- XCICHAR
01400		REPEAT 2,<JRST INPBAD>		;6,7 
01500		MOVE	X,-1(P)			;10 -- XBYTE7
01600		MOVE	X,-1(P)			;11 -- XDICHAR
01700		REPEAT 2,<JRST INPBAD>		;12,13
01800	
01900	DOSETCI:	
02000		PUSHJ	P,SETCI
02100		JRST	INPSIM
02200	
02300	.COSCI:	PUSHJ	P,COSCI
02400		JRST	INPSIM
02500	
02600	.WISCI:	PUSHJ	P,WISCI
02700		JRST	INPSIM
02800	
02900	.WOSCI:	PUSHJ	P,WOSCI
03000		JRST	INPSIM
03100	
03200	
03300		BEND INPTBL
03400	
     

00100	
00200	COMMENT ⊗ BACKUP TO BACKUP JFN ⊗
00300	
00400	;CALL TO HERE WITH A PUSHJ, WITH CDB,CHNL LOADED
00500	↑BACKUP:
00600		PUSH	P,1
00700		LDB	1,[POINT 6,OFL(CDB),5]	;BYTE-SIZE
00800		CAIN 	1,44
00900		  JRST	BACKU1
01000		SKIPE	TTYINF(CDB)	;CONTROLLING TERMINAL?
01100		  JRST	BACTTY		;YES
01200	BACBKJ:	HRRZ	1,CHNL		;THE JFN
01300		JSYS 	BKJFN
01400		  ERR <BACKUP:  Cannot do BKJFN jsys for RETAIN>,1
01500	BACRET:	POP	P,1
01600		POPJ	P,
01700	BACKU1:	SOS	IOBP(CDB)
01800		IBP	IOBP(CDB)
01900		IBP	IOBP(CDB)
02000		IBP	IOBP(CDB)
02100		IBP	IOBP(CDB)
02200		AOS	IOCNT(CDB)
02300		JRST	BACRET
02400	
02500	BACTTY:	HRRZ	1,TTYINF(CDB)
02600		CAIN	1,TNXINP			;TENEX DEFAULT
02700		  JRST	BACBKJ				;YES, USE BKJFN
02800		CAIE	1,DECLED			;DEC STYLE?
02900		CAIN	1,TENXED			;OR TENEX?
03000		  JRST	BACKU1
03100		ERR	<BACKUP:  Illegal editing mode for controlling terminal>,1
03200		JRST 	BACKU1
03300	
03400	;LINE NUMBER STUFF
03500	
03600	INLINN:
03700	NOPGNN:
03800		SKIPE	SOSNUM(CDB)	;WANT THE NUMBER?
03900		  JRST 	[MOVE TEMP,@IOBP(CDB)	;SAVE IT FOR THE USER
04000			 MOVEM TEMP,@SOSNUM(CDB)
04100			 JRST .+1]
04200		MOVE	TEMP,-1(P)	;RELOCATED TABLE
04300		SKIPGE	TEMP,LINTBL(TEMP) ;LINTBL+RLC+TABLE
04400		 JRST	 GIVLIN	; WANTS IT NEXT TIME OR SOMETHING
04500	
04600		JSP	TEMP,EATLIN	;TOSS IT OUT, AND 
04700		JRST	.IN		; CONTINUE
04800	
04900	EATLIN:
05000		AOS	IOBP(CDB)	;FORGET IT ENTIRELY
05100		MOVNI	A,5		;INDICATE SKIPPING SIX
05200		ADDB	A,IOCNT(CDB)	;IN COUNT
05300		JUMPGE	A,(TEMP)	;OVERFLOW BUFFER??
05400		PUSHJ	P,DOINP
05500		JRST	OKLN		;36-BIT RETURN
05600		ERR	<INPUT:  7-BIT BYTES CANNOT HAVE LINE NUMBERS>
05700		JRST	DONE1		;END-OF-FILE
05800	OKLN:	
05900		IBP	IOBP(CDB)	;GET OVER TAB FINALLY
06000		SOS	IOCNT(CDB)	;IS THIS RIGHT -- RLS 12/74
06100		JRST	(TEMP)		;AND CONTINUE
06200	
06300	
06400	GIVLIN:	TRNE	TEMP,-1		;WANT LINE NO IN BRCHAR WORD?
06500		 JRST	 GVLLN		;NO, WANTS IT NEXT TIME.
06600		SKIPL	TEMP,@IOBP(CDB)	;NEGATED LINE NO
06700		MOVNS	TEMP
06800		SKIPE	BRCHAR(CDB)	;USER LOCATION?
06900		MOVEM	TEMP,@BRCHAR(CDB) ;STORE WHERE HE WANTS IT
07000		JSP	TEMP,EATLIN	;GO EAT UP LINE NUMBER AND
07100		JRST	DONE1		;FINISH UP
07200	GVLLN:
07300		SKIPE	BRCHAR(CDB)
07400		  SETOM	@BRCHAR(CDB)	;TELL THE USER
07500		AOS	IOCNT(CDB)	;REVERSE THE SOSLE
07600		MOVE	Y,OFL(CDB)	;NOW CHECK TO SEE IF WE CAN DO THIS WITHOUT DISASTER
07700		TESTN	Y,WRBIT		;WRITING?
07800		TESTE	Y,APPBIT	;OR APPENDING?
07900		  ERR	<INPUT:  Give line feature not implemented when reading and writing.
08000	Continuation will cause the line number to be modified.>
08100		MOVEI	Y,1		;TURN OFF LINE NUMBER 
08200		ANDCAM	Y,@IOBP(CDB)	;  BIT
08300		MOVSI	Y,070000	;BACK UP BYTE POINTER
08400		ADDM	Y,IOBP(CDB)
08500		JRST	DONE1		;FINISH OFF IN BAZE OF GORY
08600	
08700	INPBAD:	ERR <INPUT:  Illegal JFN or bad input>
08800	
     

00100	COMMENT ⊗Realin, Realscan ⊗
00200	
00300	DSCR REAL←REALIN(CHANNEL NUMBER);
00400	CAL SAIL
00500	⊗
00600	HERE (REALIN)
00700	IFN ALWAYS,<BEGIN NUMIN>
00800		PUSHJ	P,SAVE
00900		PUSHJ	P,NUMIN		;SET UP TO GET CHARS FROM CHANNEL
01000		PUSHJ	P,RLNIN		;GOBBLE A REAL NUMBER
01100		SNGL	A,A
01200	INRETA:	MOVEM	A,RACS+A(USER)
01300	INRET:	SKIPE	BRCHAR(CDB)		;USER WANTS BREAK CHARACTER?
01400		  MOVEM Z,@BRCHAR(CDB)		;FIX UP BREAK CHARACTER
01500		SOS	IOBP(CDB)		;BACK UP TO GET IT NEXT TIME
01600		FOR II←1,4 <
01700		IBP	IOBP(CDB)>
01800		AOS	IOCNT(CDB)
01900		MOVE	LPSA,X22	;GET RID OF CHANNEL AND RET. WD
02000		JRST	RESTR
02100	
02200	HERE (REALSCAN)
02300		PUSHJ	P,SAVE
02400		PUSHJ	P,STRIN		;SET UP TO GET CHARS FROM A STRING
02500		PUSHJ	P,RLNIN
02600		SNGL	A,A
02700	STRRTA:	MOVEM	A,RACS+A(USER)
02800	STRRET:
02900		HRRZ	X,-2(P)
03000		SOJ	CDB,		;BACK UP BYTE POINTER
03100	FOR II←1,4<
03200		IBP	CDB>
03300		MOVEM	CDB,(X)
03400		AOJ	CHNL,
03500		HRRM	CHNL,-1(X)
03600		MOVEM	Z,@-1(P)	;STORE BREAK CHARACTER
03700		MOVE	LPSA,X33	;GET RID OF BRK VAR, STR ADDR
03800		JRST	RESTR
03900	
04000	FNDDIG:			;FIND DIGIT OR DECIMAL POINT, KEEP TRACK OF SIGN
04100		EXCH	A,(P)		;FIRST PUT "GET NEXT CHAR" INSTR ON STACK
04200		PUSH	P,A		;AHEAD OF RETURN WORD
04300	FNDDI1:	XCT	-1(P)		;GET NEXT CHAR
04400		CAIL	D,"0"
04500		CAILE	D,"9"
04600		CAIN	D,"."
04700		 POPJ	P,
04800		JUMPL	D,.-1		;END OF FILE OR STRING
04900		CAIN	D,"-"
05000		 TLOA	FF,NUMNEG
05100		TLZ	FF,NUMNEG	;SIGN MUST IMMEDIATELY PRECEDE NUMBER
05200		JRST	FNDDI1
05300	
05400	RLNIN:
05500		SETZ	FF,		;ZERO FLAGS
05600		PUSHJ	P,FNDDIG
05700		JUMPL	D,.+2
05800		 TLO	FF,NUMSAW
05900		PUSHJ	P,GETNUM	;TRY FOR AN INTEGER
06000		CAIE	D,"."
06100		 TRZA	C,-1		;NO DIGITS AFTER DEC PT.
06200		 PUSHJ	P,GETN1D	;FINISH UP FRACTION
06300		EXCH	C,(P)		;DIGIT COUNTS ↔ NXTCHR INSTR
06400		PUSH	P,X		;PARTIAL RESULT
06500		PUSH	P,Y
06600		PUSH	P,FF		;FLAGS
06700		PUSH	P,C		;NXTCHR INSTR
06800		SETZ	FF,		;EXPONENT FLAGS
06900		CAIE	D,"@"
07000		CAIN	D,"E"
07100		 JRST	[XCT	(P)		;EAT A CHAR
07200			CAIE	D,"@"
07300			CAIN	D,"E"
07400		RLNIN2:	 XCT	(P)		;ALLOW FOR TWO OF THESE
07500			CAIN	D,"-"
07600			 TLOA	FF,NUMNEG
07700			CAIN	D,"+"
07800			 XCT	(P)		;PAST SIGN
07900			PUSHJ	P,GETNUM	;RECURSE FOR EXPONENT
08000			PUSHJ	P,TZMUL	;GET EXPONENT AS AN INTEGER
08100			JUMPN	C,RLNIN1
08200			 ERR	<NUMIN: Improper exponent>,1	;NO DIGITS APPEARED
08300			JRST	RLNIN1
08400			]
08500		CAIN	D,"D"
08600		 JRST	RLNIN2
08700		SETZB	X,Y		;EXPONENT IS ZERO
08800		SETZ	C,		;AND THERE WERE NO DIGITS IN IT
08900	RLNIN1:
09000		MOVE	Z,D		;SAVE BRCHAR (COULD BE -1 FOR EOF)
09100		SUB	P,X11		;GET RID OF NXTCHR INSTR
09200		TLNN	FF,NUMNEG
09300		 SKIPA	D,Y		;LOW WD OF EXPONENT
09400		 MOVN	D,Y		;EXPONENT WAS NEG
09500		POP	P,FF		;FLAGS OF FRACTION
09600				;-2(P): FRACTION DIGIT COUNTS
09700				;-1(P), -0(P): FRACTION
09800		TLNN	C,-1		;IF ANY TRAILING ZEROES LEFT, A WHOPPING BIG EXP.
09900		SKIPE	X		;HIGH PART HAD BETTER BE ZERO
10000		 JRST	[SUB	P,X33	;WIPE OUT FRACTION AND DIGIT COUNTS
10100			 JRST	DFSERR]	;AND COMPLAIN
10200		POP	P,Y		;FRACTION PART
10300		POP	P,X
10400		POP	P,C		;DIGIT COUNTS OF FRACTON
10500		JRST	DFSC
10600		
10700	HEREFK(LREALIN,LREA.IN)
10800		PUSHJ	P,SAVE
10900		PUSHJ	P,NUMIN
11000		PUSHJ	P,RLNIN
11100		DMOVEM	A,RACS+A(USER)
11200		JRST	INRET
11300	
11400	HEREFK(LREALSCAN,LREA.SCAN)
11500		PUSHJ	P,SAVE
11600		PUSHJ	P,STRIN
11700		PUSHJ	P,RLNIN
11800		DMOVEM	A,RACS+A(USER)
11900		JRST	STRRET
12000	
12100	DSCR INTEGER←INTIN(CHANNEL NUMBER);
12200	CAL SAIL
12300	⊗
12400	HERE (INTIN)
12500		PUSHJ	P,SAVE
12600		PUSHJ	P,NUMIN
12700		PUSHJ	P,RLNIN
12800		SNGL	A,A
12900		PUSHJ	P,RFIX
13000		JRST	INRETA
13100	
13200	RFIX:			;SIGN(A)*FLOOR(ABS(A)+0.5) 
13300	KI10<	JUMPL	A,.+3
13400		 FIXR	A,A
13500		 POPJ	P,
13600		MOVN	A,A
13700		FIXR	A,A
13800		MOVN	A,A
13900		POPJ	P,
14000	>;KI10
14100	NOKI10<	JUMPL	A,.+4
14200		 FADRI	A,(0.5)		;SORRY, 166 !
14300		 FIX	A,A
14400		 POPJ	P,
14500		MOVN	A,A
14600		FADRI	A,(0.5)
14700		FIX	A,A
14800		MOVN	A,A
14900		POPJ	P,
15000	>;NOKI10
15100	
15200	DSCR INTEGER←INTSCAN("STRING");
15300	CAL SAIL
15400	⊗
15500	HERE (INTSCAN)
15600		PUSHJ	P,SAVE
15700		PUSHJ	P,STRIN
15800		PUSHJ	P,RLNIN
15900		SNGL	A,A
16000		PUSHJ	P,RFIX
16100		JRST	STRRTA
16200	
16300	
     

00100	;NUMIN -- CONTD.
00200	
00300	NUMIN:
00400	?NUMSIM:
00500		VALCHN	1,-2(P),NUMBAD		;1,CDB, CHNL LOADED
00600		SIMIO	Z,NUMTBL,NUMBAD		;MOVE	CHNL,1	;JFN TO 1
00700		SKIPE	ENDFL(CDB)
00800		  SETZM	@ENDFL(CDB)
00900		SETZM	.SKIP.
01000		SKIPE	BRCHAR(CDB)
01100		  SETZM	@BRCHAR(CDB)
01200	
01300		MOVE	A,[JSP A,NCH]
01400		MOVEI	Z,1			;FOR LINE NUMBER TEST
01500		POPJ	P,
01600	
01700	; READ A CHARACTER FROM INPUT FILE -- FOR SCAN.
01800	NCH:	SOSGE IOCNT(CDB);	DECREMENT CHARACTER COUNT
01900		  JRST	NUMINP
02000	
02100	NCH1:	ILDB D,IOBP(CDB);	LOAD BYTE
02200		TDNE Z,@IOBP(CDB);	CHECK FOR LINE NUMBER
02300		JRST NCH5
02400	NCH1.1:	SKIPN	LINNUM(CDB)	;WANT SETPL THINGS?
02500		   JRST	(A)		;NO RETURN
02600		CAIN	D,12		;LINE FEED?
02700		   AOS	@LINNUM(CDB)	;YES
02800		CAIE	D,14		;FORM FEED?
02900		   JRST	(A)		;NOPE, NOTHING
03000		SKIPE	PAGNUM(CDB)
03100		   AOS	@PAGNUM(CDB)	;INCREMENT PAGE COUNTER
03200		SKIPE	LINNUM(CDB)
03300		  SETZM	@LINNUM(CDB)	;AND ZERO LINE COUNTER
03400		JRST (A);		RETURN
03500	
03600	NCH7:	SETO D,		;EOF OR DATA ERROR.
03700		JRST (A)
03800	
03900	NCH5:	SKIPE	SOSNUM(CDB)	;WANT SETPL STUFF?
04000		  JRST	[MOVE	D,@IOBP(CDB)
04100			 MOVEM	D,@SOSNUM(CDB)	;INFORM USER ABOUT LINE NUMBER
04200			 JRST	.+1]
04300		AOS IOBP(CDB);		WE HAVE A LINE NUMBER
04400		MOVNI D,5;		MOVE OVER IT
04500		ADDB D,IOCNT(CDB)
04600		SKIPL	 D		;NOTHING LEFT?
04700		  JRST NCH		;DO ANOTHER INPUT
04800		PUSHJ	P,DOINP		;
04900		  JRST	NCH6		;36-BIT RETURN -- MUST BE
05000		  PUSHJ	P,NUMBAD	;IMPOSSIBLE
05100		  JRST	NCH7		;EOF OR SOME SUCH
05200	
05300	NCH6:	SOSGE IOCNT(CDB);	REMOVE TAB
05400		JRST NCH7		;NONE THERE OR ERROR
05500		IBP IOBP(CDB)
05600		JRST NCH
05700	
05800	;SETUP FOR STRING INPUT (REALSCAN, INTSCAN)
05900	STRIN:
06000		MOVE	A,[JSP A,NCHA]
06100		HRRZ	CHNL,-3(P)	;ADDR OF WD2
06200		MOVE	CDB,(CHNL)	;BP
06300		HRRZ	CHNL,-1(CHNL)	;LENGTH
06400		POPJ	P,
06500	
06600	;READ A CHARACTER ROUTINE FOR STRINGS.
06700	NCHA:	SOJL	CHNL,NCH7
06800		ILDB	D,CDB
06900		CAIN	D,15
07000		 JRST	NCHA		;IGNORE CR
07100		JUMPE	D,NCHA		;AND NUL
07200		JRST (A)
     

00100	;LNUMIN	NUMBER INPUT
00200	COMMENT ⊗
00300	These routines form a character-string
00400	to number conversion package.  GETNUM eats characters one at a time
00500	until a non-digit is eaten; GETNUM then returns intermediate information
00600	which can be used by the other routines.
00700	GETNU1 is the routine to call
00800	after GETNUM when a decimal point is seen and you eventually want a floating
00900	point number.
01000	
01100	GETNUM:	-1(P)	instruction to XCT, gets next character in D
01200		(P)	return word
01300		D	first digit
01400	result:	as in GETNU1
01500	
01600	GETNU1:	X,Y	double length partial integer result
01700		-1(P)	instruction to XCT, gets next character in D
01800		(P)	return word
01900		C	# trailing zeroes ,, power of 10 scale factor
02000		D	first digit
02100	result:	X,Y	double length partial integer result
02200		(P)	instructin to XCT, gets next character in D
02300		FF	flags (sign, overflow)
02400		C	# trailing zeroes ,, scale factor + # digits since then
02500		D	break character
02600	
02700	MAKINT:	X,Y	double length partial integer result
02800		(P)	return word
02900		FF	sign flag
03000		C	# trailing zeroes ,, junk
03100	result:	A	integer value
03200	
03300	DFSC:
03400		X,Y	double length partial integer result
03500		(P)	return word
03600		FF	flags
03700		C	# trailing zeroes ,, # digits since decimal point
03800		D	exponent
03900	result:	A,B	floating point value
04000	
04100	AC USAGE:
04200	
04300	FF	flags
04400	A,B	double temp		return word for JSP NCH
04500	C	#tz ,, # digits
04600	D	char
04700	X,Y	double integer partial result
04800	Z	1 (for testing line numbers)
04900	CHNL	channel number, or # chars left in string
05000	CDB	channel data block addr, or bp to string
05100	RF	res.
05200	LPSA	scale factor for DMUL	gen.temp.
05300	TEMP	gen. temp.
05400	USER	res.
05500	SP	res.
05600	P	res.
05700	
05800	⊗
05900	;GETNUM GETNU1
06000	
06100	NUMNEG←←400000
06200	EXPNEG←←200000
06300	NUMSAW←←100000
06400	
06500	GETNUC:	XCT	-1(P)		;GET A CHAR FIRST
06600	GETNUM:
06700		SETZB	X,Y		;INITIAL RESULT
06800		SETZ	C,		;DIGIT COUNTS
06900		JRST	2,@.+1		;CLEAR FLAGS
07000		GETNU1
07100	
07200	GETN1D:	TRZA	C,-1		;NUMBER OF DIGITS SINCE DEC. PT IS ZERO
07300	GETN1E:	AOBJN	C,.+1		;A TRAILING ZERO
07400	GETN1C:	XCT	-1(P)		;GET NEXT CHAR
07500	GETNU1:	CAIL	D,"0"
07600		CAILE	D,"9"
07700		 POPJ	P,		;NOT DIGIT
07800		SUBI	D,"0"		;CONVERT TO DIGIT NOW
07900		JUMPE	D,GETN1E	;A TRAILING ZERO
08000		ADDI	C,1		;ANOTHER DIGIT
08100		TLNE	C,-1		;WERE THERE TRAILING ZEROES BEFORE IT?
08200		 PUSHJ	P,TZMUL		;YES
08300		PUSHJ	P,M10ADD	;MULT BY =10 AND ADD D
08400		JRST	GETN1C
08500	
08600	TZMUL:	HLRZ	TEMP,C		;# TRAILING ZEROES
08700		JUMPE	TEMP,CPOPJ	;QUIT IF NONE
08800		MOVEI	C,(C)		;WILL BE NONE IF WE FINISH WITHOUT OVERFLOW
08900		CAIN	TEMP,(C)
09000		 JRST	CPOPJ		;TRAILERS WERE ALSO LEADERS!
09100		MOVEI	LPSA,(D)	;SAVE DIGIT
09200		SETZ	D,
09300		PUSHJ	P,M10ADD	;ADJUST VALUE TO ACCOUNT FOR TRAILING ZEROES
09400		SOJG	TEMP,.-2
09500		MOVEI	D,(LPSA)	;RESTORE D
09600		POPJ	P,
09700	
09800	M10ADD:
09900		MOVE	A,Y		;LOW HALF
10000		MULI	A,=10
10100		TLO	A+1,400000	;PREVENT OVERFLOW
10200		ADDI	A+1,(D)		;ADD NEW DIGIT
10300		TLZN	A+1,400000	;WOULD THERE HAVE BEEN AN OVERFLOW?
10400		 ADDI	A,1		;YES. (THIS CAN'T OVERFLOW; A WAS AT MOST 9)
10500		MOVE	D,X		;HIGH HALF
10600		IMULI	D,=10
10700		 JOV	[ADD	C,X11	;PRETEND WE HAD A TRAILING ZERO
10800			SOJA	C,CPOPJ]
10900		TLO	D,400000	;PREVENT OVERFLOW
11000		ADDI	D,(A)		;CARRY IN FROM LOW HALF
11100		TLZN	D,400000	;WOULD THERE HAVE BEEN AN OVERFLOW?
11200		 JRST	@.-4		;YES
11300		MOVEM	A+1,Y		;STORE LOW HALF
11400		MOVEM	D,X		;AND HIGH HALF
11500	CPOPJ:	POPJ	P,
11600	;DFSC
11700	
11800	;	FF	NUMNEG FLAG
11900	;	C	# TRAILING ZEROES,, # DIGITS SINCE DECIMAL PT.
12000	;	D	EXPONENT
12100	;	X,Y	FRACTION
12200	
12300	DFSC:
12400		MOVE	A,X		;BEGIN CONVERTING TO PURE FRACTION
12500		JFFO	A,DFSC1
12600		MOVE	A,X+1		;HIGH WD WAS ZERO
12700		JFFO	A,.+1
12800		ADDI	A+1,=35
12900	DFSC1:	MOVEI	LPSA,-1(A+1)	;# OF PLACES TO SHIFT (REMEMBER SIGN BIT)
13000		ASHC	X,(LPSA)	;MAKE INTO PURE FRACTION
13100		SUBI	LPSA,=70
13200		MOVN	LPSA,LPSA	;EXPONENT OF 2 OF FRACTION
13300		
13400	;***** SOMETHING FISHY HERE.  CONSIDER 12345.98@3
13500		SUBI	D,(C)		;DIGITS SINCE DECIMAL POINT DECREASE THE EXPONENT
13600		HLRZ	C,C
13700		ADDI	D,(C)		;BUT TRAILING ZEROES DONT COUNT
13800		JUMPE	D,DFSC2		;EXPONENT OF 10 IS ZERO
13900		JUMPG	D,DFSC3
14000		TLO	FF,EXPNEG	;EXPONENT WAS NEG
14100		MOVN	D,D
14200		SKIPA	TEMP,[EXP.M1,,FR.M1]	;USE THIS TABLE SINCE EXP WAS NEG
14300	DFSC3:	MOVE	TEMP,[EXP.P1,,FR.P1]	;EXP WAS POS
14400		TRNE	D,777700	;CHECK EXPONENT RANGE
14500		 JRST	DFSERR
14600		TRNE	D,40		;E+-32 INVOLVED?
14700		TLNE	FF,EXPNEG	;YES. TOO BAD IF E-48
14800		 JRST	MULOOP		;OK
14900		TRNE	D,20		;E-48 ?
15000		 JRST	DFSERR
15100	MULOOP:	TRZE	D,1		;SHOULD WE MULTIPLY?
15200		 PUSHJ	P,DMUL..	;YES
15300		JUMPE	D,DFSC2
15400		ASH	D,-1		;NEXT BIT INTO POSITION
15500		AOBJN	TEMP,.+1	;ADD 1 TO LH
15600		AOJA	TEMP,MULOOP	;AND 2 TO RH
15700	
15800	DFSC2:
15900	KI10<	DMOVE	A,X	>;KI10
16000	NOKI10<	MOVE	A,X
16100		MOVE	A+1,X+1	>;NOKI10
16200		ASHC	A,-8		;MAKE ROOM FOR EXPONENT
16300		FSC	A,200(LPSA)	;INSERT IT
16400		JFOV	DFSERR
16500	DFSC4:
16600		JUMPGE	Z,.+3		;IF RAN OUT OF CHARS
16700		 TLNE	FF,NUMSAW	; AND SAW NUMBER
16800		  MOVEI	Z,0		;  THEN FLAG IT THIS WAY
16900	KI10<	TLNE	FF,NUMNEG
17000		 DMOVN	A,A
17100		POPJ	P,
17200	>;KI10
17300	NOKI10<	TLNN	FF,NUMNEG
17400		 POPJ	P,
17500		SETCA	A,		;ONES COMPLEMENT OF HIGH WORD
17600		MOVN	A+1,A+1		;TWOS COMPLEMENT OF LOW WORD
17700		TLZ	A+1,400000	;FORCE SIGN BIT OFF
17800		JUMPN	A+1,CPOPJ	;IF LOW SIGNIFICANCE, DONE
17900		AOJA	A,CPOPJ		;OTHERWISE TWOS COMPLEMENT OF HIGH WORD
18000	>;NOKI10
18100	
18200	DFSERR:	ERR	<NUMIN: Exponent range exceeded>,1
18300		SETOB	A,A+1
18400		TLNN	FF,EXPNEG
18500		 TLZA	A,400000	;EXPONENT WAS POS, GIVE AN INFINITY
18600		SETZB	A,A+1		;EXPONENT WAS NEG, GIVE ZERO
18700		JRST	DFSC4		;OF RIGHT SIGN
18800	;DMUL..
18900	;MULTIPLY TWO DOUBLE-LENGTH PURE FRACTIONS. ONE IS (TEMP), OTHER IS X,Y PAIR
19000	;RETURN DOUBLE-LENGTH RESULT IN X,Y
19100	;SCALE FACTOR KEPT IN LPSA
19200	
19300	DMUL..:
19400	NOKL10<	PUSH	P,X		;SAVE HIGH
19500		SETZM	X		;1ST WORD, FINAL PRODUCT
19600		MOVE	A,(TEMP)	;HIGH
19700		MULM	A,Y		;* LOW
19800					;IGNORING 3RD WORDS: 8 EXPONENT BITS TO BURN
19900		MOVE	A,1(TEMP)	;LOW
20000		MUL	A,(P)		;* HIGH
20100		TLO	A,400000	;PREVENT OVERFLOWS
20200		ADD	A,Y		;ADD 2ND WORDS
20300		TLZN	A,400000	;WOULD THERE HAVE BEEN AN OVERFLOW?
20400		 AOS	X		;YES, DO CARRY (SETS X TO 1)
20500		MOVEM	A,Y		;STORE LOW RESULT
20600		POP	P,A		;HIGH
20700		MUL	A,(TEMP)	;* HIGH
20800		TLO	A+1,400000	;PREVENT OVERFLOW
20900		ADD	A+1,Y		;COLLECT 2ND WORD
21000		TLZN	A+1,400000	;WOULD THERE HAVE BEEN AN OVERFLOW?
21100		 ADDI	A,1		;YES
21200		ADD	A,X		;COLLECT 1ST WORD (THIS CAN'T OVERFLOW)
21300	>;NOKL10
21400	KL10<
21500		DMOVE	A,X
21600		DMOVEM	A+2,X
21700		DMUL	A,(TEMP)
21800		DMOVE	A+2,X
21900	>;KL10
22000		TLNE	A,(1B1)		;NORMALIZED FRACTION?
22100		 JRST	.+3		;YES
22200		ASHC	A,1		;NO, SHIFT OVER
22300		SUBI	LPSA,1		;AND ADJUST EXPONENT
22400		MOVS	TEMP,TEMP		;COLLECT EXPONENT CHANGES
22500		ADD	LPSA,(TEMP)
22600		MOVS	TEMP,TEMP
22700		MOVEM	A,X		;STORE RESULT SO FAR
22800		MOVEM	A+1,Y
22900		POPJ	P,
23000	
23100	FR.P1:	240000,,0	;10↑1		PURE FRACTION PART
23200		0
23300		310000,,0	;10↑2
23400		0
23500		234200,,0	;10↑4
23600		0
23700		276570,,200000	;10↑8
23800		0
23900		216067,,446770	;10↑16
24000		040000,,0
24100		235613,,266501	;10↑32
24200		133413,,263574
24300	EXP.P1:	4				;POWER OF 2 EXPONENT PART
24400		7
24500		16
24600		33
24700		66
24800		153
24900	
25000	FR.M1:	314631,,463146	;10↑-1
25100		146314,,631463
25200		243656,,050753	;10↑-2
25300		205075,,314217
25400		321556,,135307	;10↑-4
25500		020626,,245364
25600		253630,,734214	;10↑-8
25700		043034,,737425
25800		346453,,122766	;10↑-16
25900		042336,,053314
26000		317542,,172552	;10↑-32
26100		051631,,227215
26200	EXP.M1:	-3
26300		-6
26400		-15
26500		-32
26600		-65
26700		-152
26800	
     

00100	
00200	NUMBAD: ERR<NUMIN:  Illegal JFN, byte-size or mode>
00300		POPJ	P,
00400	
00500		BEGIN NUMTBL
00600	
00700	↑NUMTBL:JRST	DOSETCI				;0 -- XNULL
00800		MOVE    CHNL,1				;1 -- XICHAR
00900		JRST	.COSCI				;2 -- XOCHAR
01000		JRST	.WISCI				;3 -- XIWORD
01100		JRST	.WOSCI				;4 -- XOWORD
01200		MOVE	CHNL,1				;5 -- XCICHAR
01300		REPEAT 2,<JRST	NUMBAD>			;6,7
01400		MOVE	CHNL,1				;10 -- XBYTE7
01500		MOVE	CHNL,1				;11 -- XDICHAR
01600		REPEAT 2,<JRST NUMBAD>			;12,13
01700	
01800	DOSETCI:
01900		PUSHJ	P,SETCI
02000		JRST	NUMSIM
02100		
02200	.COSCI:	PUSHJ	P,COSCI
02300		JRST	NUMSIM
02400	
02500	.WISCI:	PUSHJ	P,WISCI
02600		JRST	NUMSIM
02700	
02800	.WOSCI:	PUSHJ	P,WOSCI
02900		JRST	NUMSIM
03000	
03100		BEND NUMTBL
03200	
03300	NUMINP:	PUSHJ	P,DOINP
03400		JRST	NCH				;BUFFERED INPUT
03500		JRST	NCH1.1				;7-BIT
03600		JRST	NCH7				;EOF OR ERROR
03700	
03800	
03900	RZ:	SETZ A,
04000		JRST DONE
04100	ENDCOM(NUM)
04200	COMPIL(TBB,<.CH.,.TEN.,.MT.>,,<TABLES FOR L PAUL'S ROUTINES>)
     

00100	DSCR DATA TABLES FOR REALIN, INTSCAN, ETC.
00200	⊗
00300	
00400	↑↑.CH.:	4
00500		7
00600		16
00700		33
00800		66
00900		153
01000		777777777775
01100		777777777772
01200		777777777763
01300		777777777746
01400		777777777713
01500		777777777626
01600	↑↑.MT.:	240000000000
01700		310000000000
01800		234200000000
01900		276570200000
02000		216067446770
02100		235613266501
02200		314631463147
02300		243656050754
02400		321556135310
02500		253630734215
02600		346453122767
02700		317542172553
02800	↑↑.TEN.:	1
02900		=10
03000		=100
03100		=1000
03200		=10000
03300		=100000
03400		=1000000
03500		=10000000
03600		=100000000
03700		=1000000000
03800		=10000000000
03900	
04000	ENDCOM(TBB)
04100	IFN ALWAYS,<
04200		BEND
04300	>;IFN ALWAYS
     

00100	
00200	DSCR SIMPLE PROCEDURE CHAROUT(INTEGER JFN, CHAR)
00300	⊗
00400	HERE(CHAROUT)
00500		BEGIN CHAROUT
00600		PUSHJ	P,SAVE
00700		MOVE	LPSA,X33
00800		LITCHN	1,-2(P),CHOLIT
00900	DOSIMIO:SIMIO	3,TABL,CERR		;SOSGE IOCNT(CDB)
01000		  PUSHJ	P,ADCO1
01100		MOVE	2,-1(P)
01200		IDPB	2,IOBP(CDB)
01300		JRST	RESTR
01400	
01500	TABL:	JRST	DOSETCO			;0 -- XNULL
01600		JRST	.CISCO			;1 -- XICHAR
01700		SOSGE	IOCNT(CDB)		;2 -- XOCHAR
01800		JRST	.WISCO			;3 -- XIWORD
01900		JRST	.WOSCO			;4 -- XOWORD
02000		JRST	CERR			;5 -- XCICHAR
02100		SOSGE	IOCNT(CDB)		;6 -- XCOCHAR
02200		JRST	CERR			;7 -- XCWORD
02300		JRST	DOBOUT			;10 -- XBYTE7
02400		JRST	CERR			;11 -- XDICHAR
02500		SOSGE	IOCNT(CDB)		;12 -- XDOCHAR
02600		JRST	CERR			;13 -- XDARR
02700	
02800	DOSETCO:	
02900		PUSHJ	P,SETCO
03000		JRST	DOSIMIO
03100	
03200	.CISCO:	PUSHJ	P,CISCO
03300		JRST	DOSIMIO
03400	
03500	.WISCO:	PUSHJ	P,WISCO
03600		JRST	DOSIMIO
03700	
03800	.WOSCO:	PUSHJ	P,WOSCO
03900		JRST	DOSIMIO
04000	
04100	CERR:	ERR <CHAROUT:  Illegal JFN, byte-size, or mode.>,1
04200		JRST	RESTR
04300	
04400	CHOLIT:
04500	DOBOUT:	MOVE	2,-1(P)
04600		JSYS	BOUT
04700		JRST	RESTR
04800	
04900		BEND CHAROUT
     

00100	
00200	DSCR SIMPLE PROCEDURE OUT(INTEGER JFN; STRING S)
00300	⊗
00400	HERE(OUT)
00500		BEGIN OUT
00600		PUSHJ	P,SAVE
00700		MOVE	LPSA,X22
00800		LITCHN	1,-1(P),CHKTTY
00900	DOSIMIO:SIMIO	2,TABL,CERR	;HRRZ 3,-1(SP)
01000		JUMPE	3,SOURET	;DONT SEND EMPTY STRING
01100	LOOP:	SOSGE	IOCNT(CDB)	;DECREMENT BUFFER COUNT
01200		  PUSHJ	P,ADCO1		;GET NEW BUFFER
01300		ILDB	2,(SP)		;NEXT CHAR ON STRING
01400		IDPB	2,IOBP(CDB)	;AND COPY THE CHARACTER
01500		SOJG	3,LOOP		;STRING CHAR COUNT
01600	
01700	SOURET:	SUB	SP,X22		;ADJUST STRING STACK
01800		JRST	RESTR
01900	
02000	DOSOUT:	
02100		SKIPE	CTLOSW		;IF CONTROL-O AND
02200		SKIPN	TTYINF(CDB)	;THE CONTROLLING TERMINAL
02300		  JRST 	.+2
02400		 JRST	SOURET		;THEN DONT DO OUTPUT
02500	REPEAT 0,<;BUGS IN SOUT JSYS -- ARE THEY STILL THERE??
02600	DOSOU1:	HRRZ	3,-1(SP)
02700		JUMPE	3,SOURET
02800	SOUT1:	ILDB	2,(SP)		;NEXT CHAR
02900		JSYS	BOUT
03000		SOJG	3,SOUT1		;STRING CHAR COUNT
03100		JRST	SOURET
03200	>;REPEAT 0
03300	DOSOU1:	
03400		HRRZ	3,-1(SP)	;COUNT
03500		JUMPE	3,SOURET	;DONT SEND NULL STRING
03600		MOVE	2,(SP)		;STRING BP
03700		MOVN	3,3		;NEGATIVE COUNT
03800		JSYS	SOUT		;STRING OUTPUT
03900		JRST	SOURET		;AND RETURN
04000		
04100	CERR:	ERR <OUT:  Illegal JFN, byte-size, or mode>,1
04200		JRST 	SOURET
04300	
04400	TABL:	JRST	DOSETCO		;0 -- XNULL
04500		JRST	.CISCO		;1 -- XICHAR	
04600		HRRZ 3,-1(SP)		;2 -- XOCHAR
04700		JRST	.WISCO		;3 -- XIWORD
04800		JRST	.WOSCO		;4 -- XOWORD
04900		JRST	CERR		;5 -- XCICHAR
05000		HRRZ 3,-1(SP)		;6 -- XCOCHAR
05100		JRST	CERR		;7 -- XCWORD	
05200		JRST	DOSOUT		;10 -- XBYTE7
05300		JRST	CERR		;11 -- XDICHAR
05400		HRRZ 3,-1(SP)		;12 -- XDOCHAR
05500		JRST	CERR		;13 -- XDARR
05600	
05700	DOSETCO:	
05800		PUSHJ	P,SETCO
05900		JRST	DOSIMIO
06000	
06100	.CISCO:	PUSHJ	P,CISCO
06200		JRST	DOSIMIO
06300	
06400	.WISCO:	PUSHJ	P,WISCO
06500		JRST	DOSIMIO
06600	
06700	.WOSCO:	PUSHJ	P,WOSCO
06800		JRST	DOSIMIO
06900	
07000	CHKTTY:
07100		SKIPN	CTLOSW				;CONTROL-O SWITCH ON?
07200		  JRST	DOSOU1				;NO
07300		CAIE	1,100				;CONTROLLING TERMINAL?
07400		CAIN	1,101
07500		  JRST	SOURET				;YES, RETURN
07600		JRST	DOSOU1				;NO, JUST DO IT
07700	
07800	
07900		BEND OUT
08000	
     

00100	DSCR	PROCEDURE LINOUT(INTEGER JFN,VALUE)
00200	⊗
00300	
00400	HERE(LINOUT)
00500		BEGIN LINOUT
00600	
00700		PUSHJ	P,SAVE
00800		VALCHN	A,-2(P),LINBAD
00900	DOSIMIO:SIMIO	B,TABL,LINBAD	;SKIPG	B,IOCNT(CDB)
01000		   PUSHJ P,ADCO		;NO, SEND (OR PERHAPS JUST INITIALIZE)
01100		MOVE	TEMP,IOBP(CDB)	;GET BP
01200	
01300	LINOPL:	TLNN	TEMP,760000	;LINED BP?
01400		   JRST	OKLIGN
01500		IBP	TEMP
01600		SOJA	B,LINOPL	
01700	
01800	OKLIGN:	MOVEM	TEMP,IOBP(CDB)
01900		MOVEM	B,IOCNT(CDB)
02000		CAIGE	B,=10		;ENOUGH FOR 10 CHARS?
02100		  PUSHJ	P,ADCO		;NO
02200		SKIPGE	B,-1(P)		;GET LINE-NO
02300		  JRST	[MOVNS B
02400			 MOVNI A,5
02500			 JRST	NOCONV]
02600		MOVNI	A,6
02700		MOVE	C,[<ASCII /00000/>/2]	
02800		EXCH	B,C
02900		PUSH	P,LNBAK
03000	LNCONV:	IDIVI 	C,=10
03100		IORI	D,"0"
03200		DPB	D,[POINT 7,(P),6]
03300		SKIPE	C
03400		PUSHJ	P,LNCONV	;THE RECURSIVE PRINTER
03500		HLL	C,(P)
03600		LSHC	B,7
03700	LNBAK:	POPJ	P,.+1
03800		LSH	B,1
03900		TRO	B,1
04000	NOCONV:	AOS	C,IOBP(CDB)	;MOVE A WORD OUT
04100		MOVEM	B,(C)
04200		ADDM	A,IOCNT(CDB)
04300		MOVEI	B,11
04400		CAME	A,[-5]
04500		  IDPB	B,IOBP(CDB)	;OUTPUT A TAB
04600	NOTAB:	MOVE	LPSA,X33
04700		JRST	RESTR
04800	
04900	LINBAD:	ERR <LINOUT:  Illegal JFN, byte-size, or mode>,1
05000		JRST	NOTAB
05100	
05200	TABL:	JRST	DOSETCO				;0 -- XNULL
05300		JRST	.CISCO				;1 -- XICHAR
05400		SKIPG	B,IOCNT(CDB)			;2 -- XOCHAR
05500		JRST	.WISCO				;3 -- XIWORD
05600		JRST	.WOSCO				;4 -- XOWORD
05700		JRST	LINBAD				;5 -- XCIWORD
05800		SKIPG	B,IOCNT(CDB)			;6 -- XCOWORD
05900		JRST	LINBAD				;7 -- XCWORD
06000		JRST	LINBAD				;10 -- XBYTE7
06100		JRST	LINBAD				;11 -- XDICHAR
06200		SKIPG	B,IOCNT(CDB)			;12 -- XDOCHAR
06300		JRST	LINBAD				;13 -- XDARR
06400	
06500	DOSETCO:
06600		PUSHJ	P,SETCO
06700		JRST	DOSIMIO
06800	
06900	.CISCO:	PUSHJ	P,CISCO
07000		JRST	DOSIMIO
07100	
07200	.WISCO:	PUSHJ	P,WISCO
07300		JRST	DOSIMIO
07400	
07500	.WOSCO:	PUSHJ	P,WOSCO
07600		JRST	DOSIMIO
07700	
07800	
07900		BEND LINOUT
08000	
     

00100	HERE(RCHPTR)
00200		BEGIN RCHPTR
00300		PUSHJ	P,SAVE
00400		MOVE	LPSA,X22
00500		VALCHN	1,-1(P),CERR
00600		SETZM	.SKIP.
00700	DOSIMIO:SIMIO	2,TABL,CERR
00800	STOAC2:	MOVEM	2,RACS+A(USER)
00900		JRST	RESTR
01000	
01100	TABL:	JRST	RNULL				;0 -- XNULL
01200		REPEAT 	4,<PUSHJ P,GETCPT>		;1-4
01300		REPEAT  3,<JRST CERR>			;5-7
01400		JRST	DORFPTR				;10 -- XBYTE7
01500		REPEAT	3,<JRST CERR>
01600	
01700	DORFPTR:
01800		JSYS	RFPTR
01900		  JRST	.+2
02000		JRST	STOAC2
02100	;HERE WITH AN ERROR FROM RFPTR
02200		MOVEM	1,.SKIP.
02300		JRST	RNULL
02400	
02500	CERR:	ERR	<RCHPTR:  Illegal jfn, mode, or byte size>,1
02600		SETOM	.SKIP.
02700		SETZM	RACS+A(USER)
02800		JRST	RESTR
02900	
03000	RNULL:
03100		PUSHJ	P,SETCIO
03200		JRST	DOSIMIO
03300		
03400		BEND RCHPTR
     

00100	HERE(SCHPTR)
00200		BEGIN SCHPTR
00300		PUSHJ	P,SAVE
00400		MOVE	LPSA,X33
00500		VALCHN	1,-2(P),CERR
00600		SETZM	.SKIP.
00700	DOSIMIO:MOVE	2,-1(P)				;POINTER
00800		SIMIO	3,TABL,CERR
00900		JRST	RESTR
01000	
01100	TABL:	JRST	RNULL				;0 -- XNULL .  Remember arg in 2
01200		PUSHJ	P,SETCPT			;1 -- XICHAR
01300		PUSHJ	P,SETCPT			;2 -- XOCHAR
01400		PUSHJ	P,SETCPT			;3 -- XIWORD
01500		PUSHJ	P,SETCPT			;4 -- XOWORD
01600		REPEAT 	3,<JRST CERR>			;5-7
01700		JRST	DOSFPTR				;10 -- XBYTE7
01800		REPEAT	3,<JRST CERR>			;11-13
01900	
02000	RNULL:
02100		PUSHJ	P,SETCIO
02200		JRST	DOSIMIO				;BUT GET ARGUMENT AGAIN
02300	
02400	DOSFPTR:
02500		JSYS	SFPTR
02600		  JRST	.+2				;ERROR IN 1
02700		JRST	RESTR
02800		MOVEM	1,.SKIP.
02900		ERR	<SCHPTR:  Cannot do SFPTR>,1
03000		JRST	RESTR
03100	
03200	CERR:	ERR	<Dryrout at SCHPTR>,1
03300		SETOM	.SKIP.
03400		JRST	RESTR
03500	
03600	
03700		BEND SCHPTR
     

00100	DSCR	Auxiliary routines for character i/o.
00200	⊗
00300	
00400	SETCND:	
00500	;sets the FDB so tht the byte size is 7 and the number of bytes is as in 2
00600	;1, CHNL, CDB loaded
00700	;call is PUSHJ 
00800		PUSH	P,2
00900		PUSH	P,3
01000		MOVEM	2,FDBEOF(CDB)
01100		HRLI	1,12				;OFFSET
01200		MOVEM	2,3				;NEW COUNT
01300		SETO	2,				;MASK FOR CHANGED BITS
01400		JSYS	CHFDB				;NEW NUMBER OF BYTES TO END
01500		MOVEI	2,=7
01600		MOVEM	2,FDBSZ(CDB)
01700		HRLI	1,11
01800		MOVSI	2,007700			;MASK
01900		MOVSI	3,000700			;AND CHANGED BITS
02000		JSYS	CHFDB				;NEW BYTE SIZE
02100		HRLI	1,0				;LEAVE JFN IN 1
02200		POP	P,3
02300		POP	P,2
02400		POPJ	P,
02500	
02600	GETCND:
02700	;returns in 2 the character count that addresses EOF according to the FDB
02800	;1, CDB loaded
02900		BEGIN	GETCND
03000		PUSH	P,3
03100		SKIPN	3,FDBSZ(CDB)
03200		  JRST	RET0
03300		CAIN	3,=36				;36 BITS?
03400		  JRST	RET2				;YES
03500		CAIN	3,=7				;7 BIT?
03600		  JRST	RET1				;YES
03700		CAILE	3,=36				;BETTER BE LEQ 36
03800		  ERR	<GETCND:  Byte size bigger than 36 bits>,1
03900		PUSH	P,4
04000		MOVEI	2,=36
04100		IDIVI	2,(3)				;GET THE NUMBER OF BYTES IN EACH 36-BIT WORD
04200		MOVE	3,FDBEOF(CDB)			;GET THE NUMBER OF BYTES IN THE FILE
04300		IDIVI	3,(2)				;THIS MANY WORDS -- EXTRA BYTES TO 3
04400		IMULI	3,5				;THIS MANY CHARACTERS IN THE WORDS
04500		PUSH	P,3				;SAVE ON STACK
04600		MOVEI	2,(4)				;EXTRA BYTES
04700		IMUL	2,FDBSZ(CDB)			;EXTRA BITS
04800		IDIVI	2,5				;CHARACTERS
04900		JUMPE	3,.+2				;ANYTHING LEFT OVER?
05000		  AOJ	2,				;YES
05100		POP	P,3				;GET BACK NUMBER OF CHARACTERS
05200		ADD	2,3				;PLUS THE ADDITIONAL ONES HERE -- ANSWER IN 2
05300		POP	P,4				;RESTORE
05400	POPBACK:
05500		POP	P,3		
05600		POPJ	P,				;RETURN ANSWER IN 2
05700	
05800	RET0:	SETZ	2,
05900		JRST	POPBACK
06000	
06100	RET1:	MOVE	2,FDBEOF(CDB)			;7 BIT ALREADY 
06200		JRST	POPBACK
06300	
06400	RET2:	MOVE	2,FDBEOF(CDB)			;36 BIT BYTES
06500		IMULI	2,5				;5 CHARACTERS PER BYTE
06600		JRST	POPBACK				;RETURN IT
06700	
06800		BEND GETCND
06900	
07000		BEGIN GETCPT
07100	;ROUTINES FOR CHAR EOB
07200	
07300	↑↑GETCPT:
07400	;1,CDB LOADED
07500	;RETURNS IN 2 THE END OF BUFFER CHARACTER
07600		SKIPN	2,IOBP(CDB)
07700		  POPJ	P,				;RETURN 0
07800		PUSH	P,3
07900		TLZ	2,007700
08000		TLO	2,000700			;MAKE A 7-BIT POINTER
08100		IBP	2				;INCREMENT
08200		HRRZM	2,3				;ADDRESS	
08300		HRRI	2,BYTES
08400		LDB	2,2
08500		SUB	3,IOADDR(CDB)			;SUBTRACT
08600		IMULI	3,5				;CHARACTERS
08700		ADDI	3,(2)				;PLUS THESE IN EXTRA WORD
08800		MOVE	2,IOPAGE(CDB)
08900		IMULI	2,1000*5			;PREVIOUS PAGES IN THE FILE
09000		ADDI	2,(3)				;PLUS THESE
09100		POP	P,3
09200		POPJ	P,				;RETURN IN 2
09300	
09400	
09500	↑↑GTCPT1:
09600	;1, CHNL, CDB loaded
09700	;call PUSHJ
09800	;returns the following
09900	;	2	how many characters until the end of the buffer
10000	;	3	bp to first free character
10100	;	4	count for character output
10200	;	5	count for character input
10300		SKIPN	3,IOBP(CDB)
10400		  JRST	RET
10500		TLZ	3,007700
10600		TLO	3,000700			;MAKE A 7-BIT POINTER
10700		MOVEM	3,2				;COPY IN 2
10800		IBP	2
10900		HRRZM	2,4				;ADDRESS
11000		HRRI	2,BYTES				
11100		LDB	2,2				;NUMBER OF ADDTL CHARS
11200		SUB	4,IOADDR(CDB)			;ADDRESS OF BUFFER
11300		IMULI	4,5
11400		ADDI	4,(2)
11500		MOVE	2,IOPAGE(CDB)
11600		IMULI	2,1000*5
11700		ADDI	2,(4)
11800		MOVNI	4,(4)
11900		ADDI	4,1000*5
12000		MOVEM	2,5				;SAVE 2
12100		PUSHJ	P,GETCND			;GET CHAR EOF
12200		EXCH	5,2
12300		SUB	5,2
12400		CAML	5,4
12500		  MOVEM	4,5
12600		POPJ	P,
12700	
12800	BYTES:	BYTE (7) 0,1,2,3,4
12900	
13000	RET:	SETZB	2,3				;NOT INITIALIZED
13100		SETZB	4,5
13200		POPJ	P,
13300	
13400		BEND GETCPT
13500	
13600	CHCEOF:	
13700	;CHECKS TO SEE IF CHARACTER EOF POINTER NEEDS RESETTING
13800	;1, CDB LOADED
13900		SKIPN	IOBP(CDB)			;DONT CHECK IF NOTHING THERE
14000		  POPJ	P,
14100		PUSH	P,2
14200		PUSH	P,3
14300		PUSHJ	P,GETCND			;GET CHARACTER EOF IN 2
14400		MOVEM	2,3				;SAVE IN 6
14500		PUSHJ	P,GETCPT			;GET CHARACTER EOB IN 2	
14600		CAML	2,3				;NEED RESETTING?
14700		  PUSHJ	P,SETCND			;YES
14800		POP	P,3
14900		POP	P,2
15000		POPJ	P,
15100	
     

00100	SETCPT:
00200	;1,CDB LOADED
00300	;2 HAS THE BYTE IN THE FILE TO SET TO
00400		BEGIN SETCPT
00500	
00600		MOVE	3,IOSTT(CDB)
00700		CAIN	3,XOWORD			;PREVIOUSLY DOING WORD OUTPUT?
00800		  PUSHJ	P,CHWEOF			;YES CHECK EOF
00900		CAIN	3,XOCHAR			;PREVIOUSLY DOING CHAR OUTPUT
01000		  PUSHJ	P,CHCEOF			;CHECK EOF
01100		CAMN	2,[-1]				;WANT EOF?
01200		  PUSHJ P,GETCND			;YES, GET IN 2
01300		IDIVI	2,1000*5			;PAGE BEING REQUESTED
01400		CAME	2,IOPAGE(CDB)			;SAME AS CURRENT
01500		  PUSHJ	P,SETPAGE			;NO GET NEW PAGE
01600		MOVE	2,IOADDR(CDB)
01700		MOVEM	3,5				;NUMBER OF CHARS IN THIS BUFFER
01800	 	IDIVI	3,5				;WORDS TO 3, BYTES TO 4
01900		ADDI	2,(3)				;3 STILL HAS THE CHAR IN THIS PAGE
02000		HLL	2,BPS(4)
02100		MOVEM	2,IOBP(CDB)
02200		MOVE	3,IOSTT(CDB)
02300		CAIE	3,XICHAR	
02400		CAIN	3,XIWORD
02500		  JRST	ASSUMIN
02600		MOVEI	3,XOCHAR
02700		MOVEM	3,IOSTT(CDB)
02800	FULBUF:	MOVEI	3,1000*5
02900	SUBI3:	SUBI	3,(5)
03000	STOAC3:	MOVEM	3,IOCNT(CDB)
03100		POPJ	P,
03200	ASSUMIN:
03300		MOVEI	3,XICHAR
03400		MOVEM	3,IOSTT(CDB)
03500		PUSHJ	P,GETCND			;GET THE CHARACTER END OF FILE
03600		IDIVI	2,1000*5			;PAGES IN 2, CHARS IN 3
03700		CAMGE	2,IOPAGE(CDB)			;IS REQUESTED PAGE BEYOND EOF?
03800		   JRST	EMPBUF				;YES, NO INPUT THERE
03900		CAME	2,IOPAGE(CDB)			;ON THIS PAGE?
04000		   JRST	FULBUF				;NO
04100		JRST	SUBI3				;SUBTRACT ALREADY COMMITTED
04200	
04300	EMPBUF:	SETZ	3,
04400		JRST	STOAC3
04500	
04600	BPS:	POINT 7,0,-1
04700		POINT 7,0,6
04800		POINT 7,0,13
04900		POINT 7,0,20
05000		POINT 7,0,27
05100	
05200		BEND SETCPT
     

00100	SETCIO:
00200	;1,CDB LOADED 
00300	;DECIDE WHETHER TO SETCI OR SETCO
00400		MOVEI	3,SETCI				;ASSUME CHARACTER INPUT
00500		MOVE	2,OFL(CDB)
00600		TESTN	2,RDBIT				;DOING INPUT?
00700		  MOVEI	3,SETCO				;NOPE ASSUME OUTPUT
00800		JRST	(3)				;AND POPJ RETURN
     

00100	DSCR
00200		ADCI
00300	
00400	Accepts:  1	jfn
00500		  CDB	channel data block
00600	
00700	Call:	PUSHJ
00800	
00900	Returns:	+1 for eof
01000			+2 for good input
01100	
01200	Resets values in the CDB
01300	⊗
01400	
01500		BEGIN ADCI
01600	
01700	↑↑ADCI:	PUSH	P,1
01800		PUSH	P,2
01900		PUSH	P,3
02000		SIMIO	2,TABL,ADCERR			;MOVE 3,IOPAGE(CDB)
02100		AOJ	3,				;NEXT PAGE
02200		IMULI	3,1000*5			;NEXT CHARACTER
02300		PUSHJ	P,GETCND			;CHARACTER EOF IN 2
02400		CAML	3,2				;IS IT BEYOND
02500		  JRST	ADEOF				;YES -- CONFESS THAT IT IS
02600		SUB	2,3				;COUNT CHARACTERS IN NEW BUFFER
02700		CAILE	2,1000*5			;LESS THAN A FULL BUFFER
02800		  MOVEI	2,1000*5			;NO
02900		MOVEM	2,IOCNT(CDB)
03000		AOS	2,IOPAGE(CDB)			;INCREMENT PAGE COUNTER, GET IN 2
03100		PUSHJ	P,SETPAGE			;GET NEXT PAGE
03200		MOVE	2,IOADDR(CDB)
03300		HRLI	2,440700			;MAKE A BYTE-POINTER
03400		MOVEM	2,IOBP(CDB)
03500	ADRET:	AOS	-3(P)				;INCREMENT PC WORD
03600	ADEOF:	POP	P,3				;EOF --  DONT INCREMENT
03700		POP	P,2
03800		POP	P,1
03900		POPJ	P,				;RETURN
04000	
04100	TABL:	JRST	ADCERR				;0 -- XNULL
04200		MOVE	3,IOPAGE(CDB)			;1 -- XICHAR
04300		REPEAT 3,<JRST ADCERR>			;2-4
04400		JRST	DOSIN				;5 -- XCICHAR
04500		REPEAT 3,<JRST ADCERR>			;6-10
04600		JRST	DODUMPI				;11 -- XDICHAR
04700		REPEAT 2,<JRST	ADCERR>			;12,13
04800	
04900	ADCERR:	ERR	<Dryrot at ADCI>,1
05000		JRST	ADEOF
05100	
05200	
05300	DOSIN:	MOVE	2,IOADDR(CDB)
05400		HRL	3,2
05500		HRRI	3,1(2)
05600		SETZM	(2)
05700		BLT	3,777(2)
05800		HRLI	2,444400
05900		MOVNI	3,1000
06000		JSYS	SIN
06100		CAMG	3,[-1000]
06200		  JRST	[CAMN	3,[-1000]		;EOF?
06300			  JRST	ADEOF
06400			 JRST .+1]
06500		ADDI	3,1000				;NUMBER OF WORDS READ
06600		IMULI	3,5				;NUMBER OF CHARACTERS
06700	STOCNT:	MOVEM	3,IOCNT(CDB)
06800		MOVE	2,IOADDR(CDB)
06900		HRLI	2,440700
07000		MOVEM	2,IOBP(CDB)
07100		JRST	ADRET				;AND RETURN
07200	
07300	DODUMPI:
07400		PUSH	P,1				;SAVE JFN OVER POSSIBLE DUMPI ERROR
07500		PUSH	P,4
07600		MOVE	3,IOADDR(CDB)
07700		HRL	2,3
07800		HRRI	2,1(3)
07900		SETZM	(3)
08000		BLT	2,777(3)	
08100		SOJ	3,
08200		HRLI	3,-1000				;MAKE AN IOWD
08300		MOVEI	2,3				;COMMAND LIST STARTS AT 3
08400		SETZ	4,				;AND ENDS AT 4
08500		JSYS	DUMPI
08600		  JRST	DMIERR
08700		MOVEI	3,1000*5
08800		POP	P,4
08900		POP	P,1
09000		JRST	STOCNT
09100	
09200	DMIERR:	CAIE	1,600220			;EOF?
09300		  ERR	<ADCI:  Dump mode input error>,1
09400		POP	P,4				;RESTORE
09500		POP	P,1				;PRECIOUS JFN
09600		MOVE	2,DVTYP(CDB)			;GET DEVICE TYPE
09700		CAIE	2,3				;MAGTAPE?
09800		  JRST	ADEOF				;NO, JUST INDICATE EOF
09900		SETZ	2,				;MTOPR RESET
10000		JSYS	MTOPR
10100		JRST	ADEOF				;AND SAY WE ARE AT THE END OF THE FILE
10200	
10300	
10400		BEND ADCI
10500	DOINP:
10600	;CHNL has the JFN
10700	;CDB has the channel data block
10800	;returns +1 for good buffered input
10900	;	 +2 for 7-bit input with char in D
11000	;	 +3 for eof or error
11100		BEGIN DOINP
11200		PUSH	P,1				;SAVE 1
11300		PUSH	P,2
11400		MOVE	1,CHNL				;JFN
11500		MOVE	D,IOSTT(CDB)			;D IS FREE
11600		CAIE	D,XBYTE7			;7-BIT?
11700		  JRST	DOBUFF
11800		SKIPE	TTYINF(CDB)			;CONTROLLING TERMINAL?
11900		  JRST	CHKTTY				;YES
12000	DOBIN:	JSYS	BIN
12100		JUMPE	2,CHKEOF			;IF 0 MAY BE EOF
12200		MOVEM	2,D				;STORE 
12300		JRST	DOB7
12400	;;;	MOVE	2,DVTYP(CDB)			;IS THE DEVICE A TTY?
12500	;;;	CAIE	2,12				;
12600	;;;	  JRST	DOB7
12700	;;;	CAIE	2,12				;
12800	;;;	  JRST	DOB7				;NO
12900	;;;	CAIN	D,32				;A CONTROL-Z?
13000	;;;	  JRST	DOIEOF				;YES INDICATE EOF
13100	;;;	CAIN	D,37				;PHONEY BBN EOL?
13200	;;;	  MOVEI	D,12				;A LINE-FEED
13300	;;;	JRST	DOB7				;AND RETURN
13400	
13500	CHKEOF:	JSYS	GTSTS				;BETTER CHECK
13600		TESTE	2,1B8			
13700		  JRST	DOIEOF				;YEP
13800		SETZ	D,
13900		JRST	DOB7
14000	
14100	DOIEOF:	SETOM	.SKIP.
14200		SKIPE	ENDFL(CDB)			;SPECIFIED?
14300		  SETOM	@ENDFL(CDB)			;YES
14400		AOS	-2(P)
14500	DOB7:	AOS	-2(P)
14600	DORET:	POP	P,2
14700		POP	P,1
14800		POPJ	P,
14900	
15000	
15100	DOBUFF:
15200		PUSHJ	P,ADCI
15300		  JRST	DOIEOF				;INDICATE EOF
15400		JRST	DORET
15500	
15600	CHKTTY:
15700		MOVE	2,TTYINF(CDB)			;CHECK STATUS OF TTY
15800		TESTE	2,QTTEOF			;EOF QUED?
15900		  JRST	DOIEOF				;YES
16000		SETZM	CTLOSW				;INDICATE REQUEST 
16100							;FOR INPUT
16200		HRRZ	2,2
16300		CAIN	2,TNXINP			;TENEX DEFAULT
16400		  JRST	DOBIN
16500		CAIN	2,TENXED			;TENEX STYLE EDITING?
16600		  JRST	TNXBUF				;YES
16700		CAIN	2,DECLED			;DEC STYLE BUFFERING?
16800		  JRST	DECBUF
16900		ERR	<DOINP:  Illegal buffering request for terminal>,1
17000	
17100	IMSSS<
17200	TNXBUF:
17300		BEGIN TNXBUF
17400	ORIGCNT←← =1000
17500	
17600		PUSH	P,1
17700		PUSH	P,2
17800		PUSH	P,3
17900		HRRO	1,IOADDR(CDB)		;BP TO BUFFER FOR CHAN
18000		SETZ	3,
18100		MOVEI	2,ORIGCNT		;DEFAULT LENGTH
18200		JSYS 	PSTIN
18300		MOVEI	3,ORIGCNT		;MAXIMUM
18400		SUBI	3,(2)			;GET NUMBER RECEIVED IN 3
18500		LDB	2,1			;GET THE LAST CHAR
18600		CAIE	2,15			;CARRIAGE RETURN (PROB!!)
18700		  JRST	NOTCR
18800		MOVEI	2,12			;INSERT A 12 AFTER IT
18900		IDPB	2,1
19000		AOJ	3,			;INCREMENT COUNT
19100		JRST	GOTBRK			;BREAK TENDED
19200	
19300	NOTCR:
19400		CAIE	2,32			;EOF?
19500		  JRST	GOTBRK
19600		MOVE	2,[QTTEOF]
19700		ORM	2,TTYINF(CDB)		;QUE THE END OF FILE
19800		SOJ	3,			;SUBTRACT ONE FROM COUNT -- CTRL-Z
19900	
20000	GOTBRK:	MOVEM	3,IOCNT(CDB)		;SAVE COUNT
20100		MOVE	1,IOADDR(CDB)
20200		HRLI	1,440700		;MAKE A BP
20300		MOVEM	1,IOBP(CDB)		;SAVE IT FOR USER
20400		POP	P,3			;RESTORE
20500		POP	P,2
20600		POP	P,1
20700		JRST	DORET			;AND RETURN
20800	
20900		BEND TNXBUF
21000	>;IMSSS
21100	
21200	NOIMSSS<;NON-IMSSS VERSION OF INTTY FOR THOSE WHO SUFFER
21300	;UNDER BBN'S LACK OF A SYSTEM LINE EDITOR
21400	;	March, 1978
21500	;	R. Smith
21600	;	Rutgers University
21700	;	Runtime-test added for TOPS20, to use RDTTY JSYS
21800	;instead of buffering code.  If a conditional-assembly switch
21900	;is ever added for TOPS20, this should be accomplished at
22000	;assembly time.
22100	
22200	TNXBUF:
22300		BEGIN TNXBUF
22400	ORIGCNT←← =200
22500	;AC USES  A,B,C  JSYS TEMPORARIES
22600	;	  D	 BYTEPOINTER
22700	;	  E	 COUNT, INITIALLY 0
22800	;	  Q1 (=6) ORIGINAL BP
22900		PUSH	P,A			;SAVE
23000		PUSH	P,B
23100		PUSH	P,C
23200		PUSH	P,D
23300		PUSH	P,E
23400		PUSH	P,Q1
23500		MOVE	Q1,IOADDR(CDB)
23600		HRLI	Q1,440700		;MAKE A BP
23700	TSTT20:	HRROI	A,[ASCIZ/NUL/]		
23800		JSYS	STDEV			
23900		  JRST	ISTENEX			;TENEX
24000	IST20:	MOVE	A,Q1			;USE BP
24100		HRLI	B,(1B1)			;BREAK ON ↑G,↑L,↑Z,ESC,CR,LF
24200		HRRI	B,ORIGCNT		;COUNT
24300		SETZ	C,			;NO CONTROL-R FEATURE
24400	OPDEF 	RDTTY	[104000000523]
24500		RDTTY				;DO IT
24600		  JRST	[ERR <RDTTY FAILED ON TOPS20?>,0]
24605		MOVEI	E,ORIGCNT		;CALCULATE NUMBER OF BYTES LONG
24610		SUBI	E,(B)			;SINCE RH(B) CONTAINS UPDATED CONT
24800		JRST	CNTEXH			;STORE COUNT,BP, AND RETURN
24900	
24950	ISTENEX:
25000	RESTRT:	MOVE	D,Q1			;GET THE ORIGINAL BP	
25100		SETZ	E,			;ZERO THE COUNT
25200	INLUP:	CAIL	E,ORIGCNT
25300		  JRST	CNTEXH			;COUNT EXHAUSTED
25400		JSYS	PBIN			;GET A CHAR
25500		CAIN	A,37			;EOL?
25600		  JRST	DOEOL			;YES
25700		CAIN	A,12			;LINE FEED (ON TOPS 20)
25800		  JRST	DONE			;YES
25900		CAIN	A,33			;ESCAPE?
26000		  JRST	DONE
26100	 	CAIN	A,7			;CTRL-G
26200		  JRST	DONE
26300		CAIN	A,32			;CTRL-Z
26400		  JRST	TTYEOF			;INDICATE EOF
26500		CAIN	A,"R"-100		;CTRL-R FOR REPEAT
26600		  JRST	DOCTR
26700		CAIN	A,"X"-100		;CTRL-Z FOR DELETE LINE
26800		  JRST	DOCTX			;YES
26900		CAIE	A,177			;EITHER RUBOUT
27000		CAIN	A,"A"-100		;OR CTRL-A
27100		  JRST	DOCTA			;FOR DELETE CHARACTER
27200		IDPB	A,D
27300		AOJA	E,INLUP			;CONTINUE
27400	
27500	DOCTR:	HRROI	A,[ASCIZ/
27600	/]
27700		JSYS	PSOUT
27800		JUMPE	E,INLUP
27900		MOVEI	A,101
28000		MOVE	B,Q1			;ORIG BP
28100		MOVN	C,E			;COUNT THUS FAR
28200		JSYS	SOUT
28300		JRST	INLUP			;AND CONTINUE
28400	
28500	DOCTX:	HRROI	A,[ASCIZ/
28600	/]
28700		JSYS	PSOUT
28800		JRST	RESTRT			;AND START ALL OVER
28900	
29000	DOCTA:	JUMPLE	E,DOCTX			;IF NO CHARS THEN DO A CONTROL-X
29100		MOVEI	A,"\"
29200		JSYS	PBOUT
29300		LDB	A,D			;LAST CHAR
29400		JSYS	PBOUT	
29500		SOJ	D,
29600		IBP	D
29700		IBP	D
29800		IBP	D
29900		IBP	D
30000		SOJA	E,INLUP			;SUBTRACT 1 AND CONTINUE
30100	
30200	DOEOL:	
30300		MOVEI	A,15
30400		IDPB	A,D
30500		AOJ	E,
30600		MOVEI	A,12
30700	DONE:	IDPB	A,D
30800		AOJ	E,
30900	CNTEXH:
31000		MOVEM	E,IOCNT(CDB)			;COUNT
31100		MOVEM	Q1,IOBP(CDB)			;BP
31200		POP	P,Q1				;RESTORE
31300		POP	P,E
31400		POP	P,D
31500		POP	P,C
31600		POP	P,B
31700		POP	P,A
31800		JRST	DORET				;RETURN
31900	
32000	TTYEOF:	MOVE	A,[QTTEOF]
32100		ORM	A,TTYINF(CDB)			;QUE END-OF-FILE
32200		JRST	CNTEXH				;AND RETURN
32300		BEND TNXBUF
32400	>;NOIMSSS
32500	
32600	DECBUF:
32700		BEGIN DECBUF
32800	
32900	ORIGCNT ←← =1000				;LOTS OF ROOM
33000	
33100		PUSH	P,A
33200		PUSH	P,B
33300		PUSH	P,C
33400		PUSH	P,D
33500		PUSH	P,E
33600		PUSH	P,Q1
33700	
33800		MOVE	Q1,IOADDR(CDB)
33900		HRLI	Q1,440700			;MAKE A BP
34000		
34100	RESTRT:	MOVE	D,Q1
34200		SETZ	E,				;COUNT
34300	INLUP:	CAIL	E,ORIGCNT			;BEYOND?
34400		  JRST	CNTEXH				;YES
34500		JSYS	PBIN
34600		CAIN	A,DELLINE			;DELETE ENTIRE LINE?
34700		  JRST	CTRLU				;YES
34800		CAIN	A,RUBCHAR			;RUBOUT?
34900		  JRST	RUBOUT				;YES
35000		CAIN	A,37				;PHONEY BBN EOL?
35100		  JRST	SAWEOL
35200		CAIN	A,33
35300		  JRST	SAWESC
35400		CAIN	A,32				;CONTROL-Z?
35500		  JRST	TTYEOF				;YES, EOF
35600		CAIE	A,7				;CONTROL-G
35700		CAIN	A,12				;OR LF
35800		  JRST	DONE
35900		IDPB	A,D
36000		AOJA	E,INLUP				;CONTINUE
36100	
36200	CTRLU:	HRROI	A,[BYTE (7) 7,15,12,0,0]
36300		JSYS	PSOUT
36400		JRST	RESTRT				;START OVER
36500	
36600	RUBOUT:	JUMPE	E,CTRLU				;NOTHING, DO CTRLU
36700	IMSSS <
36800		MOVEI	1,101
36900		JSYS	DELCH
37000		  JFCL
37100		JRST	DLTED
37200		JRST	DLTED
37300	>;IMSSS
37400		MOVEI	A,"\"
37500		JSYS	PBOUT
37600		LDB	A,D				;LAST CHAR
37700		JSYS	PBOUT
37800	DLTED:
37900		SOJ	D,				;DECREMENT BP
38000		IBP	D
38100		IBP	D
38200		IBP	D
38300		IBP	D
38400		SOJA	E,INLUP				;DECREMENT COUNT AND CONTINUE
38500	
38600	DONE:
38700		IDPB	A,D
38800		AOJ	E,
38900	CNTEXH:
39000		MOVEM	E,IOCNT(CDB)
39100		MOVEM	Q1,IOBP(CDB)
39200		POP	P,Q1
39300		POP	P,E
39400		POP	P,D
39500		POP	P,C
39600		POP	P,B
39700		POP	P,A
39800		JRST	DORET
39900	
40000	SAWEOL:	MOVEI	A,15				;SIMULATE CR
40100		IDPB	A,D
40200		AOJ	E,
40300		MOVEI	A,12				;SIMULATE LF
40400		JRST	DONE
40500	
40600	SAWESC:	MOVEI	A,ALTMODE			;DEC ALTMODE
40700		JRST	DONE
40800	
40900	TTYEOF:	MOVE	A,[QTTEOF]
41000		ORM	A,TTYINF(CDB)			;QUE AN EOF
41100		JRST	CNTEXH				;AND RETURN
41200	
41300		BEND DECBUF
41400	
41500		BEND DOINP
     

00100	DSCR 	ADCO,ADCO1
00200	CAL	PUSHJ
00300	SID	SAVES ALL ACS
00400	ARGS
00500		1		JFN
00600		CDB		address of channel data block
00700	⊗
00800	
00900		BEGIN ADCO
01000	;HERE IF THE COUNT ALREADY PROMISES A CHARACTER
01100	↑↑ADCO1:
01200		AOS	IOCNT(CDB)	;MAKE THE COUNT HONEST, TEMPORARILY
01300		PUSHJ	P,ADCO		;CALL ADCO
01400		SOS	IOCNT(CDB)	;REFLECT THE FACT THAT A CHARACTER IS PROMISED
01500		POPJ	P,		;AND RETURN (TO CHARACTER OUTPUT CODE)
01600	
01700	↑↑ADCO:
01800		PUSH	P,2		;SAVE ACS
01900		PUSH	P,3
02000		PUSH	P,4
02100		MOVE	2,IOSTT(CDB)	;GET STATUS
02200		CAIE	2,XOCHAR	;PMAPPING THE DSK?
02300		  JRST	NOPMAP		;GUESS NOT
02400		AOS	2,IOPAGE(CDB)	;NEXT PAGE
02500		PUSHJ	P,SETPAGE
02600		MOVEI	2,1000*5	
02700		MOVEM	2,IOCNT(CDB)	;CAN WRITE THIS MANY
02800		MOVE	2,IOADDR(CDB)	
02900		HRLI	2,440700	
03000		MOVEM	2,IOBP(CDB)	;OK
03100	ADRET:	POP	P,4
03200		POP	P,3
03300		POP	P,2
03400		POPJ	P,
03500	
03600	
03700	NOPMAP:
03800		CAIN	2,XCOCHAR	;36-BIT ETC.?
03900		  JRST	STRSOU		;USE SOUT
04000		CAIE	2,XDOCHAR	;BETTER BE DUMP-MODE
04100		  ERR	<Dryrot at ADCO>,1
04200		SKIPN	IOBP(CDB)	;SET UP YET?
04300		  JRST	DMPINIT
04400		MOVE	3,IOADDR(CDB)
04500		MOVEI	4,DMOCNT*5
04600		CAMG	4,IOCNT(CDB)	;ANY CHARS TO SEND
04700		  JRST	ADRET
04800		
04900		MOVEI	2,3
05000		SUBI	3,1
05100		MOVNI	4,DMOCNT	;WORD COUNT FOR DUMP MODE OUTPUT	
05200		HRL	3,4		;MAKE AN IOWD
05300		SETZ	4,		;MAKE A COMMAND LIST
05400		JSYS DUMPO
05500		  ERR <DUMPOUT:  CANNOT WRITE DATA IN DUMP MODE>,1
05600		SETOM	DMPED(CDB)	;AND INDICATE DONE
05700	DMPINIT:
05800		MOVE	3,IOADDR(CDB)
05900		HRL	2,3
06000		HRRI	2,1(3)
06100		SETZM	(3)
06200		BLT	2,DMOCNT-1(3)	;ZERO OUT
06300		MOVEI	2,DMOCNT*5	
06400		MOVEM	2,IOCNT(CDB)	;SAVE COUNT
06500		HLL	3,[POINT 7,0,-1];FIX A BYTE-POINTER
06600		MOVEM	3,IOBP(CDB)	;AND SAVE BYTE-POINTER
06700		JRST	ADRET
06800	
06900	STRSOU:	
07000		SKIPN	IOBP(CDB)
07100		  JRST	SOUINIT
07200		MOVEI	3,1000*5
07300		SUB	3,IOCNT(CDB)	;NUMBER OF CHARACTERS ACTUALLY IN BUFFER
07400		IDIVI	3,5		;NUMBER OF WORDS
07500		SKIPE	4		;ANY REMAINDER?
07600		   AOJ	3,		;YES, ANOTHER WORD FOR EXTRA CHARACTERS
07700		JUMPE	3,ADRET		;RETURN IF NO CHARACTERS TO SEND
07800		MOVN	3,3		;NEGATIVE WORD COUNT FOR SOUT
07900		MOVE	2,IOADDR(CDB)
08000		HRLI	2,444400	;MAKE A BP
08100		JSYS SOUT
08200	SOUINIT:
08300		MOVE	2,IOADDR(CDB)
08400		HRL	3,2
08500		HRRI	3,1(2)
08600		SETZM	(2)
08700		BLT	3,777(2)	;CLEAR OUT PAGE
08800		HRLI	2,440700
08900		MOVEM	2,IOBP(CDB)
09000		MOVEI	3,1000*5
09100		MOVEM	3,IOCNT(CDB)
09200		JRST	ADRET
09300	
09400		BEND ADCO
     

00100	DSCR SETIO
00200		Master routine to set up the file io possibilities.
00300	
00400	Arguments:
00500		1,CHNL,CDB set up
00600	
00700	There are four entries to the function, depending on the kind of IO that
00800	appears to be desired.  They are:
00900	
01000		SETCI		character input
01100		SETCO		character output	
01200		SETWI		word input
01300		SETWO		word output
01400	
01500	
01600	This routine does the following things:
01700		(1)  sets up IOSTT
01800	
01900	
02000	It does so by first deciding each of these
02100		(1)  input or output immediately desired
02200		(2)  chars or words immediately desired
02300		(3)  7 or 36 bit bytes open
02400		(4)  mode 0 or 17	
02500		(5)  dsk or non-dsk
02600	
02700	An additional consideration is that the file, if on the disk,
02800	may need to be CLOSFed and reOPENFed to allow reading (and writing
02900	if appending).
03000	This facilitates (indeed, makes possible) PMAPping the file and
03100	doing I/O directly into pages of the file.  Should this reOPENF
03200	fail (as when protection does not allow it), it will be necessary
03300	to restrict the possibility of doing data mixed and random I/O
03400	to the file.  Such is the design of TENEX. (Example:  MESSAGE.TXT
03500	is ordinarily such that you can append to it but not read and
03600	write, when it is someone else's file.)
03700	⊗
03800	
03900		BEGIN SETIO
04000	↑SETWI:	SKIPA	6,[=8]				;wants word input
04100	↑SETWO:	MOVEI	6,=24				;wants word output
04200		JRST	SETIO				;
04300	
04400	↑SETCI:	TDZA	6,[-1]				;wants character input
04500	↑SETCO:	MOVEI	6,=16				;wants character output
04600	
04700	SETIO:	LDB	2,[POINT 6,OFL(CDB),5]		;7-36 BIT BYTES?
04800		CAIN	2,=36
04900		  ADDI	6,4				;36
05000		LDB	2,[POINT 4,OFL(CDB),9]
05100		JUMPE	2,.+2				;MODE 0 OR 17?
05200		  ADDI	6,2				;17
05300		SKIPE	DVTYP(CDB)			;DSK OR NON-DSK?
05400		  AOJ	6,				;NON-DSK
05500		IDIVI	6,7				;SET UP FOR LDB
05600		LDB	6,BPS(7)
05700		JUMPN	6,.+2			
05800		  ERR	<DRYROT at SETIO:  Nonsense combination of bytes and modes for io request.>,1
05900		MOVEM	6,IOSTT(CDB)			;THAT IS THE ANSWER
06000		CAIL	6,XICHAR			;PMAPPED DISK FILE?
06100		CAILE	6,XOWORD
06200		  JRST	NOPMAP
06300		MOVE	2,OFL(CDB)
06400		TESTN	2,WRBIT				;WRITING
06500		TESTE	2,APPBIT			;OR APPENDING?
06600		  JRST	.+2				;THEN BETTER BE READING
06700		JRST	CHKED1
06800		TESTO	2,RDBIT				;MUST BE READING
06900		TESTN	2,APPBIT			;REMEMBER IF APPENDING
07000		  JRST	NOAPP				;NOT APPENDING
07100		TESTZ	2,APPBIT			;TURN OFF APPENDING
07200		TESTO	2,WRBIT				;INDICATE WRITING
07300		SKIPA	3,[-1]				;APPENDING
07400	NOAPP:	  SETZ	3,				;NOT APPENDING
07500		CAMN	2,OFL(CDB)			;DIFFERENT?
07600		  JRST	CHKED				;NO
07700		TESTO	1,1B0				;DONT RELEASE
07800		JSYS	CLOSF
07900		  ERR	<SETIO:  Cannot do CLOSF>
08000		TESTZ	1,1B0				;RESET DONT RELEASE BIT
08100		PUSH	P,1				;SAVE JFN
08200		JSYS	OPENF
08300		  JRST  NOROPN				;CANNOT RE-OPEN FILE
08400		POP	P,1				;RESTORE JFN
08500		MOVEM	2,OFL(CDB)			;AND REMEMBER NEW FLAGS
08600	CHKED:	SKIPA	2,3				;PICK UP SAVED POINTER
08700	CHKED1:	  SETZ	2,
08800		PUSH	P,2				;SAVE POINTER
08900		SETOM	IOPAGE(CDB)			;DENY THAT THERE IS A PAGE THERE
09000		MOVE	2,[XWD 2,11]			;READ FDB
09100		MOVEI	3,2
09200		JSYS	GTFDB
09300		MOVEM	3,FDBEOF(CDB)			;SAVE EOF
09400		LDB	2,[POINT 6,2,11]
09500		MOVEM	2,FDBSZ(CDB)
09600		POP	P,2				;GET POINTER BACK
09700		CAIE	6,XIWORD			;SEE IF WORDS
09800		CAIN	6,XOWORD
09900		  JRST	SETWPT				;WORDS	   POPJ BACK
10000		JRST	SETCPT				;CHARACTERS  POPJ BACK
10100	
10200	NOROPN:	POP	P,1				;CLOBBERED JFN
10300		MOVE	2,OFL(CDB)			;FLAGS AS THEY WERE -- CANT DO NO BETTER
10400		JSYS	OPENF
10500		  ERR	<SETIO:  Cannot do OPENF>
10600		MOVE	2,IOSTT(CDB)			;STATUS -- MUST BE CHANGED
10700		CAIN	2,XICHAR
10800		  MOVEI	3,XCICHAR
10900		CAIN	2,XOCHAR
11000		  MOVEI	3,XCOCHAR
11100		CAIE	2,XIWORD
11200		CAIN	2,XOWORD
11300		  MOVEI	3,XCIWORD
11400		MOVEM	3,IOSTT(CDB)			;SAVE STATUS -- BEST WE CAN DO
11500							;FALL THRU AND RETURN
11600	NOPMAP:	SETZM	IOCNT(CDB)
11700		SETZM	IOBP(CDB)			
11800		POPJ	P,	
11900	
12000	
12100	BPS:	POINT	5,TABL(6),4			;BYTE POINTERS
12200		POINT	5,TABL(6),9
12300		POINT	5,TABL(6),14
12400		POINT	5,TABL(6),19
12500		POINT	5,TABL(6),24
12600		POINT	5,TABL(6),29
12700		POINT	5,TABL(6),34	
12800	
12900	TABL:	BYTE (5) XBYTE7,XBYTE7,0,0,XICHAR,XCICHAR,XDICHAR
13000		BYTE (5) XDICHAR,0,0,0,0,XIWORD,XCIWORD
13100		BYTE (5) XDARR,XDARR,XBYTE7,XBYTE7,0,0,XOCHAR
13200		BYTE (5) XCOCHAR,XDOCHAR,XDOCHAR,0,0,0,0
13300		BYTE (5) XOWORD,XCIWORD,XDARR,XDARR
13400	
13500	
13600		BEND SETIO
     

00100	DSCR
00200		FINIO
00300	
00400		Finishes the io.  
00500		Mainly does the following:
00600	
00700		(1)  outputs any remaining buffers
00800		(2)  checks eof pointer in FDB of dsk files
00900		(3)  writes EOF marks to magtape
01000	
01100	CAL	PUSHJ from runtimes (CFILE and CLOSF)
01200	ARGS	1,CDB
01300	SID	nothing saved
01400	⊗
01500	HERE(FINIO)
01600		BEGIN FINIO
01700		PUSH	P,1
01800		PUSH	P,2
01900		PUSH	P,3
02000		PUSH	P,4
02100		PUSH	P,5
02200		PUSH	P,6
02300		SIMIO	2,TABL,POPBACK
02400	UNMAP:	SETZM	DMPED(CDB)			;RESET VALUES TO ORIGINALS
02500		SETZM	IOCNT(CDB)
02600		SETZM	IOBP(CDB)
02700		SETZM	IOSTT(CDB)
02800		SETOM	IOPAGE(CDB)			;N.B.
02900		SETO	1,				;DESTROY PAGE -- NOTE: CLOBBERS JFN 
03000	 	MOVE	2,FKPAGE(CDB)			;UNTIL POP BELOW
03100		SETZ	3,
03200		JSYS	PMAP
03300	POPBACK:POP	P,6
03400		POP	P,5
03500		POP	P,4
03600		POP	P,3
03700		POP	P,2
03800		POP	P,1
03900		POPJ	P,
04000	
04100	TABL:	JRST	POPBACK				;0 -- XNULL
04200		JFCL					;1 -- XICHAR
04300		PUSHJ	P,CHCEOF			;2 -- XOCHAR -- POPJ RETURN
04400		JFCL					;3 -- XIWORD
04500		PUSHJ	P,CHWEOF			;4 -- XOWORD
04600		JFCL					;5 -- XCICHAR
04700		PUSHJ	P,ADCO				;6 -- XCOCHAR
04800		JFCL					;7 -- XCWORD
04900		JRST 	DOB7				;10 -- XBYTE7
05000		JFCL					;11 -- XDICHAR
05100		JRST	XDO1				;12 -- XDOCHAR
05200		JRST	XDO2				;13 -- XDARR
05300		
05400	DOB7:	SKIPN	2,TTYINF(CDB)			;A TELETYPE?
05500		  JRST	UNMAP				;NOPE
05600		TESTZ	2,QTTEOF			;TURN OFF QUED EOF
05700		MOVEM	2,TTYINF(CDB)
05800		JRST	UNMAP				;AND UNBUFFER
05900	
06000	XDO1:	PUSHJ	P,ADCO				;WRITE OUT WHATEVER IS THERE		
06100	XDO2:	SKIPN	DMPED(CDB)			;DUMP MODE OUTPUT SEEN?
06200		  JRST	UNMAP				;NOPE
06300		MOVE	2,DVTYP(CDB)			;DEVICE TYPE
06400		CAIE	2,2				;MAGTAPE?
06500		  JRST	UNMAP				;NOPE
06600		MOVEI	2,3				;EOF
06700		JSYS	MTOPR				;WRITE TWO
06800		JSYS	MTOPR		
06900		MOVEI	2,17				;BACKSPACE OVER 1 EOF
07000		JSYS	MTOPR
07100		JRST	UNMAP
07200	
07300	
07400		BEND FINIO
     

00100	ENDCOM(IOROU)
00200	
00300	COMPIL(BINROU,<SFPTR,RFPTR,MTOPR,BKJFN,RFBSZ>
00400		,<SAVE,RESTR,X22,X33,X44,.SKIP.,JFNTBL,CDBTBL>
00500		,<BINROU -- Binary routines generally to not be used>)
00600	
     

00100	DSCR SIMPLE PROCEDURE SFPTR(INTEGER JFN,POINTER)
00200		Sets the file open on JFN to byte POINTER (-1 for EOF).
00300	Errors returned in .SKIP.
00400		WARNING:  presently not compatible with special character
00500	mode.
00600	⊗
00700	HERE(SFPTR)
00800		PUSHJ	P,SAVE
00900		MOVE	LPSA,X33
01000		VALCHN 1,-2(P),SFBAD
01100		SETZM	.SKIP.
01200		MOVE 2,-1(P)
01300		JSYS SFPTR
01400		  MOVEM	1,.SKIP.
01500	SFRET:	JRST	RESTR
01600	
01700	SFBAD:  ERR <Illegal JFN>,1
01800		SETOM	.SKIP.
01900		JRST	SFRET
02000	
02100	
     

00100	DSCR INTEGER SIMPLE PROCEDURE RFPTR(INTEGER JFN)
00200		Reads the pointer of JFN.  Error codes to .SKIP.
00300		WARNING:  presently does not work for files in special character
00400	mode.
00500	⊗
00600	HERE(RFPTR)
00700		PUSHJ	P,SAVE
00800		MOVE	LPSA,X22
00900		VALCHN	1,-1(P),RFBAD
01000		SETZM	.SKIP.
01100		JSYS RFPTR
01200		MOVEM 1,.SKIP.
01300		MOVEM	2,RACS+A(USER)	;ANSWER IN 2
01400	RFRET:	JRST	RESTR
01500	
01600	RFBAD:  ERR <Illegal JFN>,1
01700		SETOM	.SKIP.
01800		JRST	RFRET
01900	
     

00100	DSCR SIMPLE PROCEDURE MTOPR(INTEGER JFN,FUNCTION,VALUE)
00200		Does the MTOPR jsys.
00300	⊗
00400	HERE(MTOPR)
00500		BEGIN MTOPR
00600		PUSHJ	P,SAVE
00700		MOVE	LPSA,X44
00800		VALCHN 1,-3(P),MTBAD
00900		MOVE 	2,-2(P)
01000		MOVE	3,-1(P)
01100		JSYS MTOPR
01200	MTRET:	JRST	RESTR
01300	
01400	MTBAD:  ERR <Illegal JFN>,1
01500		JRST	MTRET
01600	
01700		BEND MTOPR
01800	
     

00100	DSCR SIMPLE PROCEDURE BKJFN(INTEGER JFN)
00200		Does the BKJFN jsys on JFN, error code to .SKIP.
00300	⊗
00400	HERE(BKJFN)
00500		PUSHJ	P,SAVE
00600		MOVE	LPSA,X22
00700		VALCHN 1,-1(P),BKBAD
00800		SETZM	.SKIP.
00900	BKJF1:	JSYS BKJFN
01000		MOVEM 1,.SKIP.			;ERROR RETURN
01100	BKRET:	JRST	RESTR
01200	
01300	BKBAD:  MOVE	1,-1(P)			;USE LITERALLY
01400		JRST	BKJF1
     

00100	DSCR INTEGER SIMPLE PROCEDURE RFBSZ(INTEGER JFN);
00200		Reads the byte-size of the file open on JFN.
00300	⊗
00400	HERE(RFBSZ)
00500		PUSHJ	P,SAVE
00600		MOVE	LPSA,X22
00700		VALCHN 1,-1(P),RFBBAD
00800		JSYS RFBSZ
00900		  JFCL				;TOPS 20 ERROR RETURN
01000		MOVEM	2,RACS+A(USER)		;ANSWER IN 2
01100	RFBRET:	JRST	RESTR
01200	
01300	RFBBAD: ERR <Illegal JFN>,1
01400		JRST	RFBRET
01500	
01600	ENDCOM(BINROU)
01700	
     

00100	COMPIL(DSKOPS,<DSKIN,DSKOUT>
00200		,<JFNTBL,CDBTBL,.SKIP.>
00300		,<DSKOPS -- DIRECT DSK ROUTINES>)
00400	
00500	DSCR SIMPLE PROCEDURE 
00600	DSKIN(INTEGER MODULE,RECNO,COUNT; REFERENCE INTEGER LOC);
00700	
00800		IMSSS only.
00900		Does direct IO from the DSK (formerly device "PAK").
01000	Modules 4-7 are legal for everyone.  Other modules require enabled
01100	status.
01200		Count words are read into user's core at location LOC, from
01300	MODULE, record RECNO.  Error bits are in .SKIP.
01400		Does the DSKOP jsys (as modified at IMSSS).
01500	⊗
01600	
01700		BEGIN DSKOPS
01800	HERE(DSKIN)
01900	NOIMSSS<
02000		ERR	<DSKIN:  Only defined in IMSSS system>
02100	>;NOIMSSS
02200		PUSHJ	P,SAVE
02300		SETZ	4,		;INDICATE READ ONLY
02400	
02500	DSK1:	HRRZ	2,-2(P)
02600		JUMPLE	2,DSBAD	;LEQ 0 -- ERROR
02700		CAILE	2,1000		;DONT READ MORE THAN 1000 WORDS
02800		   JRST DSBAD
02900		IOR	2,4		;PICK UP READ OR WRITE (SET IN 4)
03000		HRLZ	1,-4(P)		;MODULE
03100		HRR	1,-3(P)		;RECORD NO. IN RIGHT HALF
03200		TLO	1,600000	;SOFTWARD ADDRESS, IMSSS FORMAT (BITS 0 AND 1 RES.)
03300		HRRZ 	3,-1(P) 		; GET THE USER LOCATION
03400	    	JSYS DSKOP
03500	DSDUN:	MOVEM 1,.SKIP.		; SAVE ERROR BITS
03600	DSRET:	MOVE 	LPSA,[XWD 5,5]	; TO ADJUST STACK
03700		JRST	RESTR
03800	DSBAD:	ERR <DSKIN OR DSKOUT:  WORD COUNT EITHER <= 0 OR > '1000>,1
03900		SETOM	.SKIP.
04000		JRST	DSRET
04100	
04200	
04300	
     

00100	DSCR SIMPLE PROCEDURE 
00200		DSKOUT(INTEGER MODULE,RECNO,COUNT; REFERENCE INTEGER LOC)
00300	DESR Similar to DSKIN, except that a write is done.
00400	⊗
00500	
00600	HERE(DSKOUT)
00700	NOIMSSS<
00800		ERR	<DSKOUT:  Only defined at IMSSS>
00900	>;NOIMSSS
01000		PUSHJ	P,SAVE
01100		MOVSI	4,(1B14)	;INDICATE WRITE (TO BE IOR'ED INTO AC 2)
01200		JRST	DSK1		;AND TO THE ABOVE CODE
01300	
01400		BEND DSKOPS
01500	
01600	ENDCOM(DSKOP)
01700	
     

00100	COMPIL(DEVS,<DEVTYPE,DVCHR,ERSTR>
00200		,<X22,X44,.SKIP.,JFNTBL,CDBTBL>
00300		,<DEVS -- DEVICE HANDLERS, ERROR ROUTINE>)
00400	DSCR INTEGER SIMPLE PROCEDURE DEVTYPE(INTEGER JFN);
00500		Returns (via the DEVCHR jsys) the device type of
00600	the device open on JFN.  The more general DEVCHR call is
00700	also implemented (below).
00800	⊗
00900	HERE(DEVTYPE)
01000		VALCHN 1,-1(P),DEVBAD
01100		JSYS DVCHR
01200		HLRZ	1,2
01300		ANDI	1,777
01400	DEVRET:	SUB	P,X22
01500		JRST	@2(P)
01600	DEVBAD: ERR <Illegal JFN>,1
01700		JRST	DEVRET
     

00100	DSCR INTEGER SIMPLE PROCEDURE DVCHR(INTEGER JFN; REFERENCE INTEGER AC1,AC3);
00200		Does the DEVCHR jsys, returning the flags from AC2 as the
00300	value of the call, and AC1 and AC3 get the contents of ac's 1 and 3.;
00400	⊗
00500	HERE(DVCHR)
00600		VALCHN 1,-3(P),DVBAD
00700		JSYS DVCHR
00800		MOVEM	1,@-2(P)
00900		MOVEM	3,@-1(P)
01000		MOVE	1,2
01100	DVRET:	SUB	P,X44
01200		JRST	@4(P)
01300	DVBAD: ERR <Illegal JFN>,1
01400		JRST	DVRET
01500		
01600	
     

00100	DSCR SIMPLE PROCEDURE ERSTR(INTEGER ERRNO,FORK)
00200		Using the ERSTR jsys, types out on the console the TENEX error string
00300	associated with ERRNO for FORK fork (0 for the current fork).  Parameters (in
00400	the sense of the ERSTR jsys) are expanded.
00500		Types out the string ERSTR:  UNDEFINED ERROR number if
00600	something is with your error number or fork (and sets .SKIP. to -1).
00700	⊗
00800	HERE(ERSTR)
00900		SETZM	.SKIP.
01000		MOVEI	1,101		;PRIMARY OUTPUT
01100		SKIPN	2,-1(P)		;ANY FORK MENTIONED?
01200		   MOVEI 2,400000	;ASSUME CURRENT FORK
01300		HRLZ	2,2		;IN LEFT HALF
01400		HRR	2,-2(P)		;THE ERROR NUMBER
01500		SETZ	3,		;NO LIMIT TO SIZE OF STRING
01600		JSYS ERSTR
01700		   JRST	ERSERR		
01800		   JRST	ERSERR		;ERROR RETURNS
01900	ERSRET:	SUB	P,X33
02000		JRST	@3(P)
02100	ERSERR:	HRROI	1,[ASCIZ/
02200	ERSTR:  UNDEFINED ERROR NUMBER
02300	/]
02400		JSYS PSOUT
02500		SETOM	.SKIP.		;INDICATE ERROR 
02600		JRST	ERSRET
02700	ENDCOM(DEVS)
02800	
     

00100	COMPIL(UTILITY,<SETCHN,ZSETST,ZADJST,.RESET,RDSEG>
00200		,<CORGET,GOGTAB,JFNTBL,CDBTBL,STRNGC,INSET,SAVE,RESTR,X33>
00300		,<UTILITY -- UTILITY TENEX ROUTINES>)
00400	DSCR
00500		SETCHN accepts in A the JFN, and returns in A the channel number associated with a JFN.  
00600	It sets up the JFNTBL, the CDBTBL table, and returns the address of the
00700	file command block in ac CDB.  Other acs are not modified (except USER).
00800		In order to accommodate the OPEN statement, a channel will be
00900	considered allocated when it has a CDB, even if it does not yet have a jfn.
01000	⊗
01100	
01200	HERE(SETCHN)
01300		MOVE	USER,GOGTAB
01400		PUSH	P,B
01500		PUSH	P,C
01600		PUSH	P,D
01700		MOVEI	B,JFNSIZE		;FOR COMPARISON TO RH OF A
01800		CAILE	B,(A)			;IS THE JFN BEYOND THE NUMBER OF CHANNELS
01900		SKIPE	CDBTBL(A)		;OR IS IT ALLOCATED OR USED?
02000		   JRST FNDCHN			;PERHAPS NOT, FIND ONE SOMEHOW
02100		HRRZ	D,A			;USE JFN NO. AS CHANNEL
02200	;MUST GET A CHANNEL DATA BLOCK
02300	GTCDB:	MOVEI	C,IOTLEN
02400		PUSHJ	P,CORGET
02500		   ERR <SETCHN:  NO CORE>
02600		MOVE	CDB,B
02700		MOVEM	CDB,CDBTBL(D)		;SAVE ADDR OF CDB
02800	;HERE WITH B,CDB, D LOADED WITH: CDBADDR,CDBADDR,CHANNEL
02900	CLCDB:	
03000		HRL	B,B
03100		ADDI	B,1
03200		SETZM	(CDB)
03300		BLT	B,IOTLEN-1(CDB)
03400	
03500	GOTCHN:	
03600		MOVEM 	A,JFNTBL(D)
03700		HRRZ	1,A			;JFN
03800		JSYS DVCHR			;CLOBBERS 1,2,3
03900		MOVEM	1,DVDSG(CDB)		;SAVE DESIGNATOR
04000		MOVEM	2,DVCH(CDB)		;AND CHARACTERISTICS
04100		HLRZ	1,2
04200		ANDI	1,777			;GET DEVICE TYPE
04300		MOVEM	1,DVTYP(CDB)		;AND SAVE IT
04400		CAIE	1,12			;IS IT A TTY?
04500		  JRST	NOTTTY			;NOPE
04600	;CHECK THAT IT IS DEVICE "TTY" (IN WHICH CASE IT IS THE CONTROLLING TERM)
04700		HRRZ	2,JFNTBL(D)		;GET JFN
04800		TRNE	2,400000		;A TERMINAL SPECIFIER FROM SETCHAN?
04900		  JRST	NOTTTY			;YES, NOT DEVICE "TTY"
05000		PUSH	P,3			;SOME SPACE
05100		PUSH	P,4
05200		PUSH	P,5
05300		PUSH	P,6
05400		HRROI	1,4
05500		MOVSI	3,200000		;DEVICE FIELD ONLY
05600		SETZ	4,
05700		JSYS	JFNS
05800		MOVEM	4,2			;SAVE IN 2
05900		POP	P,6			;RESTORE ACS
06000		POP	P,5
06100		POP	P,4
06200		POP	P,3
06300		CAME	2,[ASCIZ/TTY/]		;DEVICE TTY?
06400		  JRST	NOTTTY			;NOT THE CONTROLLING TERMINAL
06500		MOVE	2,[ISCTRM+TENXED]	;DEFAULT -- TENEX STYLE
06600		MOVEM	2,TTYINF(CDB)
06700	
06800	NOTTTY:	MOVEI	2,STARTPAGE(D)		;PAGE FOR BUFFER
06900		HRLI	2,400000		;THIS FORK
07000		MOVEM	2,FKPAGE(CDB)		;XWD FORK,PAGE FOR PMAPPING
07100		LSH	2,9			;MAKE AN ADDRESS
07200		MOVEM	2,IOADDR(CDB)		;AND SAVE IT AS WELL
07300		SETOM	IOPAGE(CDB)		;DENY THAT THERE IS A PAGE THERE
07400		HRRZ	A,D			;CHANNEL INTO A
07500		POP	P,D			;RESTORE
07600		POP	P,C			
07700		POP	P,B
07800		POPJ	P,
07900	
08000	
08100	;FIND AN OPEN CHANNEL AND RETURN THE NUMBER IN D
08200	;A HAS THE JFN NO. IN IT, SO CHECK TO SEE IF THE SAME
08300	;B MAY BE CLOBBERED
08400	FNDCHN:	HRRZ	D,JFNTBL(A)		;CHECK OLD JFN
08500		CAIE	D,(A)			;SAME AS THE NEW?
08600		  JRST  FNDCH2			;NO
08700		MOVE	CDB,CDBTBL(D)		;GET OLD CDB
08800		MOVE	B,CDB			;COPY CDB ADDR FOR BLT
08900		JRST	CLCDB			
09000	
09100	FNDCH2:	SETZ	D,
09200	FNDCH1:	CAIL	D,JFNSIZE
09300		   ERR <SETCHN:  JFN TABLE IS FULL (SHOULD NEVER HAPPEN)>
09400		SKIPE	CDBTBL(D)		;IS IT EMPTY?
09500		  AOJA	D,FNDCH1	   	;NO LOOK SOME MORE
09600		JRST	GTCDB			;YES, USE IT
09700	
09800	
09900	DSCR SIMPLE INTEGER PROCEDURE ZSETST(INTEGER I);
10000	
10100		Internal book-keeping routine not intended for
10200	use from SAIL.  Causes liberation from SAIL.
10300	
10400		THE ARGUMENT IS THE MAXIMUM SIZE OF THE EXPECTED STRING.
10500	THE RETURN IS THE BYTEPOINTER POINTING INTO THE TOP OF STRING SPACE
10600	⊗
10700	
10800	HERE(ZSETST)
10900		MOVE USER,GOGTAB 		; GET USER
11000		SKIPE	SGLIGN(USER)
11100		  PUSHJ	P,INSET			;ASSUMING THAT IT IS TRANSPARENT FOR THE ACS
11200		MOVE	1,-1(P)		;GET EXPECTED LENGTH
11300		ADDM 1,REMCHR(USER) 		; ADD ON
11400		SKIPLE REMCHR(USER) 		; NEED TO COLLECT?
11500		  PUSHJ P,GOCOLLECT 		; YES
11600		MOVE 1,TOPBYTE(USER) 		; RETURN BP
11700		SUB P,X22 			; ADJUST STACK
11800		JRST @2(P) 			; RETURN
11900	
12000	GOCOLLECT:	
12100		MOVEM	RF,RACS+RF(USER)	;SAVE RF
12200		PUSHJ P,STRNGC ;
12300		POPJ P, 			; RETURN TO ABOVE
12400	
     

00100	DSCR STRING SIMPLE PROCEDURE ZADJST(INTEGER CNTEST,BP)
00200		Internal book-keeping routine.
00300		ADJUSTS THE PARAMETERS ASSOCIATED WITH STRING SPACE.
00400	BP IS OUR NEW TOPBYTE.  CNTEST IS THE COUNT ESTIMATE WE
00500	ORIGINALLY MADE.
00600		FIRST, WE MUST MAKE REMCHR HONEST, THEN WE
00700		CAN FIX TOPSTR AND THE USER'S LENGTH WORD.
00800	⊗
00900	HERE(ZADJST)
01000		BEGIN ZADJST
01100	
01200	
01300		MOVE USER,GOGTAB;	
01400		PUSH	P,1
01500		PUSH	P,2
01600		PUSH	P,3
01700		PUSH	P,4
01800	
01900	DEFINE CNTARG <-6(P)>
02000	DEFINE BPARG <-5(P)>
02100	
02200		MOVE	2,BPARG			;UPDATED BP
02300		MOVE 	1,TOPBYTE(USER) 	; GET OLD TOPBYTE
02400		CAMN 	1,2 			; THE NULL STRING?
02500		  JRST NULRET;			;YES
02600	;P. KANERVA'S BYTE ROUTINE
02700		LDB	3,[POINT 6,1,5]		;BITS TO THE RIGHT OF BYTE 1
02800		LDB	4,[POINT 6,2,5]		;BITS TO THE RIGHT OF BYTE 2
02900		SUBI	3,(4)			;BIT DIFFERENCE
03000		IDIVI	3,7			;WITHIN-WORD BYTE DIFFERENCE
03100		
03200		SUBI	2,(1)			;WORDS BETWEEN BYTES
03300		HRRE	2,2			;FULL WORD DIFFERENCE
03400		IMULI	2,5			;CONVERT IT TO BYTE DIFFERENCE
03500		ADD	2,3			;ADD COUNT DERIVED FROM WITHIN-WORD
03600						;DIFFERENCE
03700	
03800		CAMLE	2,CNTARG		;WITHIN RANGE?
03900		  ERR <ZADJST:  TENEX WROTE TOO LONG A STRING, MAY BE FATAL>,1
04000	GOTLNG:	HRRO	1,2			; XWD -1,COUNT
04100		PUSH 	SP,1 			; XWD -1,COUNT
04200	       	PUSH 	SP,TOPBYTE(USER) 	; OLD TOPBYTE FOR BP FOR STRING
04300		JUMPE	2,NOLNG
04400		MOVE	1,BPARG
04500		MOVEM	1,TOPBYTE(USER)
04600	NOLNG:
04700		SUB 	2,CNTARG		; SUBTRACT THE COUNT ESTIMATE
04800		ADDM 	2,REMCHR(USER) 		; MAKE REMCHR HONEST
04900		POP	P,4
05000		POP	P,3			
05100		POP	P,2
05200		POP	P,1
05300		SUB 	P,X33 			; ADJUST STACK
05400		JRST @3(P) ;
05500	
05600	NULRET:	SETZ 2,;
05700		JRST GOTLNG 			; BE SURE TO FIX UP ALL THE GOODIES
05800		
05900		BEND ZADJST
06000	
     

00100	DSCR
00200		.RESET
00300	SID	SAVES ALL ACS
00400	CAL	JSP P,.RESET  from SAILOR
00500	
00600		RESETS TENEX IO AND BOOKKEEPING, AND SETS THE TTY MODE TO WAKEUP
00700	ON EVERY CHARACTER.  TTY WAKEUP IS NOT DONE IF THE JOB IS DETACHED.
00800	THIS SHOULD ONLY BE CALLED FROM SAILOR.
00900	⊗
01000	HERE(.RESET)
01100	BEGIN RESET
01200	;ZERO OUT BOOKKEEPING
01300		SETZM	JFNTBL
01400		MOVE	1,[XWD JFNTBL,JFNTBL+1]
01500		BLT	1,JFNTBL+JFNSIZE-1
01600		SETZM	CDBTBL
01700		MOVE	1,[XWD CDBTBL,CDBTBL+1]
01800		BLT	1,CDBTBL+JFNSIZE-1
01900	
02000	;RELEASE PAGES ASSOCIATED WITH FILES (FROM STARTPAGE TO STARTPAGE+JFNSIZE-1)
02100		SETO	1,			;RELEASE PAGE
02200		SETZ	3,			;FLAGS WORD
02300		MOVE	2,[XWD 400000,STARTPAGE]
02400	.RESE1:	CAMN	2,[XWD 400000,STARTPAGE+JFNSIZE]	;THIS WOULD BE TOO MANY PAGES
02500		  JRST .RESE2
02600		JSYS	PMAP			
02700		AOJA	2,.RESE1		;NEXT?
02800	
02900	.RESE2:
03000		JSYS RESET		;CLEAR ALL IO
03100	
03200	;SET UP PSI SYSTEM
03300		HRRZI	1,400000	;USE EXISTING TABLE IF THERE
03400	;;	JSYS	RIR
03500	;;	JUMPN	2,.+3		;ALREADY THERE
03600		MOVE	2,[XWD LEVTAB,CHNTAB]
03700		JSYS	SIR
03800		JSYS	EIR		;TURN ON INTERRUPTS
03900	
04000	;CHECK AND SEE IF WE ARE DETACHED
04100		JSYS	GJINF
04200		CAMN	4,[-1]		;-1 FOR DETACHED JOBS
04300		  JRST	DTCHED		;YES IT IS DETACHED
04400	
04500	;SET PRIMARY INPUT TO WAKE UP ON EVERY CHARACTER
04600	;THE USER MAY RESET THIS.
04700		MOVEI	1,100		;PRIMARY INPUT
04800		JSYS RFMOD
04900		TRO	2,170000	;WAKEUP ON ALL CHARS
05000		JSYS SFMOD
05100	DTCHED:	SETZM	CTLOSW		;CLEAR OUTPUT-SUPPRESSION SWITCH
05200	
05300		JRST	(P)		;AND RETURN
05400	BEND RESET
05500	
05600	;ROUTINE TO CHECK IF A JFN HAS BEEN CLOSED BY ONE OF
05700	;THE DEC-STYLE CLOSE ROUTINES (IN WHICH CASE IT
05800	;MUST BE AVAILABLE FOR RE-OPENING)
05900	;ARGS:
06000	;	1	JFN
06100	;	CDB	THE CHANNEL DATA BLOCK
06200	↑OPNCHK:
06300		SKIPL	IOSTT(CDB)		;CLOSED BY DEC?
06400		   POPJ P,			;NO
06500		PUSH	P,2			;SAVE 2
06600		MOVE	2,OFL(CDB)		;PREVIOUSLY USED FLAGS
06700		JSYS	OPENF			;OPEN
06800		   ERR <OPNCHK:  Cannot OPENF file>,1
06900		SETZM	IOSTT(CDB)
07000		POP	P,2			;RESTORE 2
07100		POPJ	P,			;RETURN
07200	
07300	HERE(RDSEG)
07400		PUSHJ	P,SAVE			;
07500		MOVE	LPSA,X33		;FOR RESTR BELOW
07600		HRRZ	A,SEGPAGE*1000 + 12	;ADDRESS OF LAST WORD OF SEGMENT IS HERE
07700		LSH	A,-=9			;MAKE IT A PAGE NUMBER
07800		HRLI	A,SEGPAGE		;FIRST PAGE OF SEGMENT
07900		MOVEM	A,@-2(P)		;STORE
08000		HRLI	A,STARTPAGE		;FIRST WORD OF BUFFER REGION
08100		HRRI	A,STARTPAGE+JFNSIZE-1	;LAST PAGE OF BUFFER REGION
08200		MOVEM	A,@-1(P)		;STORE
08300		JRST	RESTR			;AND RETURN
08400	
08500	ENDCOM(UTILITY)
     

00100	COMPIL(TTM,<RFMOD,SFMOD,STPAR,STI,RFCOC,SFCOC,GTTYP,STTYP,SETEDIT>
00200		,<SAVE,RESTR,X22,X33,X44>
00300		,<TTM -- TERMINAL MODE ROUTINES>)
00400	
00500	DSCR INTEGER PROCEDURE RFMOD(INTEGER CHAN)
00600	
00700		Reads a file's mode word.
00800	
00900	     PROCEDURE SFMOD(INTEGER CHAN,AC2)
01000	
01100		Sets a file's mode word to argument AC2.
01200	
01300	     PROCEDURE STPAR(INTEGER CHAN,BITS)
01400	
01500		Executes the STPAR jsys on CHAN with arguments BITS
01600	
01700	     PROCEDURE STI(INTEGER CHAN,CHAR)
01800	
01900		Executes the STI jsys on CHAN with character CHAR.
02000	
02100	     PROCEDURE RFCOC(INTEGER CHAN; REFERENCE INTEGER AC2,AC3)
02200	
02300		Does RFCOC jsys, returning values in AC2 and AC3.
02400	
02500	     PROCEDURE SFCOC(INTEGER CHAN,AC2,AC3)
02600	
02700		Does SFCOC jsys, setting to AC2 and AC3.
02800	
02900	     INTEGER PROCEDURE GTTYP(INTEGER CHAN; REFERENCE INTEGER BUFS)
03000	
03100		Does GTTYP jsys on CHAN/TTY and returns the
03200		typ information as the value of the call.  BUFS is the
03300		result from AC 3.
03400	
03500	     PROCEDURE STTYP(INTEGER CHAN,NEWTYPE)
03600	
03700		Sets the terminal type of CHAN to NEWTYPE
03800	
03900	⊗
04000	
04100	HERE(RFMOD)
04200		PUSHJ	P,SAVE
04300		MOVE	LPSA,X22
04400		VALCH1	1,-1(P),RFMO1
04500	RFMO2:	JSYS	RFMOD
04600		MOVEM	2,RACS+A(USER)
04700		JRST	RESTR
04800	RFMO1:	MOVE	1,-1(P)		;USE LITERALLY
04900		JRST	RFMO2
05000	
05100	
05200	
05300	HERE(SFMOD)
05400		PUSHJ	P,SAVE
05500		MOVE	LPSA,X33
05600		VALCH1	1,-2(P),SFMO1
05700	SFMO2:	MOVE	2,-1(P)
05800		JSYS SFMOD
05900		JRST	RESTR
06000	SFMO1:	MOVE	1,-2(P)
06100		JRST	SFMO2
06200	
06300	HERE(STPAR)
06400		PUSHJ	P,SAVE
06500		MOVE	LPSA,X33
06600		VALCH1	1,-2(P),STPAR1
06700	STPAR2:	MOVE	2,-1(P)		;PARAMETERS TO SET
06800		JSYS	STPAR		;EXECUTE JSYS
06900		JRST	RESTR
07000	STPAR1:	MOVE	1,-2(P)		;USE LITERALLY
07100		JRST	STPAR2
07200	
07300	HERE(STI)
07400		PUSHJ	P,SAVE
07500		MOVE	LPSA,X33
07600		VALCH1	1,-2(P),STI1
07700	STI2:	MOVE	2,-1(P)
07800		JSYS	STI
07900		JRST	RESTR
08000	STI1:	MOVE	1,-2(P)		;USE LITERALLY
08100		JRST	STI2
08200		
08300	
08400	HERE(RFCOC)
08500		PUSHJ	P,SAVE
08600		MOVE	LPSA,X44
08700		VALCH1	1,-3(P),RFCO1
08800	RFCO2:	JSYS	RFCOC
08900		MOVEM	2,@-2(P)
09000		MOVEM	3,@-1(P)
09100		JRST	RESTR
09200	RFCO1:	MOVE	1,-3(P)		;USE LITERALLY
09300		JRST 	RFCO2
09400	
09500	HERE(SFCOC)
09600		PUSHJ	P,SAVE
09700		MOVE	LPSA,X44
09800		VALCH1	1,-3(P),SFCO1
09900	SFCO2:	MOVE	2,-2(P)
10000		MOVE	3,-1(P)	
10100		JSYS	SFCOC
10200		JRST	RESTR
10300	SFCO1:	MOVE	1,-3(P)		;USE LITERALLY
10400		JRST	SFCO2
10500	
10600	HERE(GTTYP)
10700		PUSHJ	P,SAVE
10800		MOVE	LPSA,X33
10900		VALCH1	1,-2(P),GTTYP1
11000	GTTYP2:	JSYS	GTTYP
11100		MOVEM	2,RACS+A(USER)	;TERMINAL TYPE NUMBER FOR RETURN
11200		MOVEM	3,@-1(P)	;XWD INBUFS, OUTBUFS
11300		JRST	RESTR
11400	GTTYP1:	MOVE	1,-2(P)		;USE LITERALLY
11500		JRST	GTTYP2
11600	
11700	HERE(STTYP)
11800		PUSHJ	P,SAVE
11900		MOVE	LPSA,X33
12000		VALCH1	1,-2(P),STTYP1
12100	STTYP2:	MOVE	2,-1(P)		;NEW TERMINAL TYPE
12200		JSYS	STTYP
12300		JRST	RESTR
12400	STTYP1:	MOVE	1,-2(P)		;USE LITERALLY
12500		JRST	STTYP2
12600	
12700	HERE(SETEDIT)
12800		PUSHJ	P,SAVE
12900		MOVE	LPSA,X33
13000		VALCHN	1,-2(P),SETTT1
13100		SKIPL	2,TTYINF(CDB)	;IS IT THE CONTROLLING TERMINAL?
13200		  JRST	SETTT2		;NO RETURN(0);
13300		HRRZ	2,2		;OLD VALUE
13400		MOVE	2,["B"
13500			   "D"
13600			   "T"](2)
13700		HRRZM	2,RACS+A(USER)	;RETURN OLD VALUE
13800		MOVE	2,-1(P)		;NEW VALUE
13900		CAIL	2,"a"
14000		CAILE	2,"z"
14100		  JRST 	.+2
14200		 SUBI	2," "		;UPPER CASE
14300		CAIN	2,"B"
14400		  JRST	[MOVEI 2,TNXINP
14500			 JRST  SETTT3]
14600		CAIN	2,"D"
14700		  JRST	[MOVEI 2,DECLED
14800			 JRST	SETTT3]
14900		CAIN	2,"T"
15000		  JRST	[MOVEI 2,TENXED
15100			 JRST	SETTT3]
15200		  ERR	<SETEDIT:  Buffering mode must be "B", "D" or "T">,1
15300		MOVEI	2,TENXED	;ASSUME THIS FOR USER
15400	SETTT3:	HRRM	2,TTYINF(CDB)
15500		JRST	RESTR		;AND RETURN
15600	
15700	SETTT1:	ERR <SETEDIT:  Channel argument must be a SAIL channel>,1
15800		JRST	RESTR
15900	
16000	SETTT2:	SETZM	RACS+A(USER)
16100		JRST	RESTR
16200	
16300	ENDCOM(TTM)
16400	
     

00100	COMPIL(PAGES,<PMAP>,<SAVE,RESTR,X44>
00200		,<PAGES -- PAGE MANAGEMENT>)
00300	DSCR SIMPLE PROCEDURE PMAP(INTEGER AC1,AC2,AC3);
00400	DESR
00500		Does the PMAP jsys, with these parameters:
00600	
00700	ARGUMENTS:	
00800		AC1		contents of AC1
00900		AC2		  "	 of AC2
01000		AC3		  "	 of AC3
01100	
01200	⊗
01300	HERE(PMAP)
01400		PUSHJ	P,SAVE
01500		MOVE	LPSA,X44
01600		MOVE	1,-3(P)			;FILEPAGE
01700		MOVE	2,-2(P)			;XWD FORK,PAGE
01800		MOVE 	3,-1(P)			;ACCESS BITS
01900		JSYS PMAP
02000		JRST	RESTR
02100	ENDCOM(PAGES)
     

00100	COMPIL(TT2,<PBTIN,INTTY>
00200		,<X22,.SKIP.,ZSETST,ZADJST,CTLOSW>
00300		,<TT2 -- IMSSS TTY ROUTINES>)
00400	
00500	DSCR INTEGER SIMPLE PROCEDURE PBTIN(INTEGER SECONDS);
00600	DESR 
00700		Executes the PBTIN jsys, with timing of SECONDS.
00800	⊗
00900	HERE(PBTIN)
01000	NOIMSSS<
01100		ERR	<PBTIN:  Only defined at IMSSS>
01200	>;NOIMSSS
01300		SETZM	CTLOSW			;PROGRAM REQUESTS INPUT
01400		MOVE	1,-1(P)			;TIME IN SECONDS
01500		JSYS PBTIN
01600		SUB	P,X22
01700		JRST	@2(P)
01800	
     

00100	DSCR STRING SIMPLE PROCEDURE INTTY;
00200		Using the PSTIN jsys, accepts as many as 200 characters from
00300	the user's Teletype, with the standard system breakcharacters.  The
00400	breakcharacter itself is removed from the string, and
00500	no timing is available.
00600	⊗
00700	IMSSS<
00800	HERE(INTTY)
00900		PUSH	P,1
01000		PUSH	P,2
01100		PUSH	P,3
01200		SETZB	3,CTLOSW		;PROGRAM REQUESTS INPUT
01300		MOVEI	2,=200			;DEFAULT LENGTH
01400	INTT2:	PUSH	P,2			;LENGTH
01500		PUSHJ	P,ZSETST		;GET BP IN 1
01600		JSYS PSTIN
01700		CAIL	2,=200			;DID WE GET 200 CHARS?
01800		   JRST	[SETOM	.SKIP.
01900			 JRST	INTT1]
02000		LDB	3,1			;GET THE LAST CHAR
02100		MOVEM	3,.SKIP.		;AND SAVE IT
02200		SOJ	1,			;BACK UP BYTE-POINTER (OVER LAST CHAR)
02300		IBP	1
02400		IBP	1
02500		IBP	1
02600		IBP	1
02700	INTT1:	PUSH	P,[=200]
02800		PUSH	P,1
02900		PUSHJ	P,ZADJST		;GET STRING ON STACK
03000		POP	P,3	
03100		POP	P,2
03200		POP	P,1
03300		POPJ	P,			;RETURN
03400	>;IMSSS
03500	
03600	
     

00100	NOIMSSS<;NON-IMSSS VERSION OF INTTY FOR THOSE WHO SUFFER
00200	;UNDER BBN'S LACK OF A SYSTEM LINE EDITOR
00300	
00400	DSCR INTTY
00500		Simulation of the above routine, doing something
00600	that looks like "TENEX" line editing.
00700	⊗;
00800	HERE(INTTY)
00900		BEGIN INTTY
01000	ORIGCNT←←=200
01100	;AC USES  A,B,C  JSYS TEMPORARIES
01200	;	  D	 BYTEPOINTER
01300	;	  E	 COUNT, INITIALLY 0
01400	;	  Q1 (=6) ORIGINAL BP
01500	
01600	
01700		PUSHJ	P,SAVE
01800		SETZM	CTLOSW
01900	;GACK--TEST FOR TOPS20 OR TENEX.  THIS CODE SHOULD BE REMOVED
02000	;SOMEDAY, WHEN TENEX GOES AWAY, OR WHEN A CONDITIONAL
02100	;COMPILATION SWITCH IS PUT IN FOR TOPS20
02200		HRROI	A,[ASCIZ/NUL/]
02300		JSYS	STDEV			;TEST FOR TENEX
02400		  JRST	ISTENEX			;IT IS TENEX
02500	IST20:	
02600		PUSH	P,[ORIGCNT]
02700		PUSHJ	P,ZSETST		;GET A BP IN A
02800		HRLI	B,(1B1+1B4)		;BREAK ON CHARS, SUPPRESS CR,
02900						;RETURNING LF ONLY
03000		HRRI	B,ORIGCNT		;COUNT IN RH(B)
03100		SETZ	C,
03200	OPDEF	RDTTY	[104000000523]
03300		RDTTY				;READ TTY INPUT
03400		 JRST	[ERR <RDTTY FAILED ON TOPS20?>,0]
03500		LDB	C,A			;GET THE LAST CHAR
03600		MOVEM	C,.SKIP.		;AND SAVE IT
03700		SOJ	A,			;BACK UP BYTE-POINTER (OVER LAST CHAR)
03800		IBP	A
03900		IBP	A
04000		IBP	A
04100		IBP	A
04200	INTT1:	PUSH	P,[=200]		;ADJUST STRING SPACE
04300		PUSH	P,A
04400		PUSHJ	P,ZADJST		;GET STRING ON STACK
04500		MOVE	LPSA,X11		
04600		JRST	RESTR			;AND RETURN
04700		
04800	ISTENEX:
04900		MOVEI	A,101
05000		JSYS	RFMOD
05100		PUSH	P,B			;SAVE THE TTY MODE
05200		TRO	B,170000		;WAKEUP ON EVERYTHING
05300		JSYS	SFMOD
05400		
05500		PUSH	P,[ORIGCNT]		;
05600		PUSHJ	P,ZSETST		;GET A GOOD BP IN A
05700		MOVE	Q1,A
05800	RESTRT:	MOVE	D,Q1			;GET THE ORIGINAL BP	
05900		SETZ	E,			;ZERO THE COUNT
06000	INLUP:	CAIL	E,ORIGCNT
06100		  JRST	CNTEXH			;COUNT EXHAUSTED
06200	INLU1:	JSYS	PBIN			;GET A CHAR
06300		CAIN	A,15			;CARRIAGE RETURN?
06400		  JRST	INLU1			;YES, IGNORE
06500		CAIN	A,37			;EOL?
06600		  MOVEI	A,12			;MAKE LINEFEED
06700		CAIN	A,12
06800		  JRST	DONE			;IS A BREAK CHARACTER
06900		CAIN	A,33			;ESCAPE?
07000		  JRST	DONE
07100		CAIE	A,32			;CTRL-Z
07200	 	CAIN	A,7			;CTRL-G
07300		  JRST	DONE
07400		CAIE	A,"R"-100		;CTRL-R FOR REPEAT
07500		  JRST	NOCTR	
07600		HRROI	A,[ASCIZ/
07700	/]
07800		JSYS	PSOUT
07900		JUMPE	E,INLUP
08000		MOVEI	A,101
08100		MOVE	B,Q1			;ORIG BP
08200		MOVN	C,E			;COUNT THUS FAR
08300		JSYS	SOUT
08400		JRST	INLUP			;AND CONTINUE
08500	NOCTR:	CAIE	A,"X"-100		;CONTROL-X FOR DELETE LINE
08600		  JRST	NOCTX
08700	DOCTX:	HRROI	A,[ASCIZ/
08800	/]
08900		JSYS	PSOUT
09000		JRST	RESTRT			;AND START ALL OVER
09100	NOCTX:	CAIE	A,177			;RUBOUT OR
09200		CAIN	A,"A"-100		;CONTROL-A
09300		  JRST	.+2
09400		 JRST	NOCTA
09500		JUMPLE	E,DOCTX			;IF NO CHARS THEN DO A CONTROL-X
09600		MOVEI	A,"\"
09700		JSYS	PBOUT
09800		LDB	A,D			;LAST CHAR
09900		JSYS	PBOUT	
10000		MOVE	A,D
10100		JSYS	BKJFN
10200		  JFCL
10300		MOVEM	A,D			;BACK UP BP
10400		SOJA	E,INLUP			;SUBTRACT 1 AND CONTINUE
10500	NOCTA:	IDPB	A,D
10600		AOJA	E,INLUP			;ONE MORE CHAR	
10700	
10800	CNTEXH:	SETO	A,			;INDICATE NO COUNT
10900	DONE:	MOVEM	A,.SKIP.		;BREAK CHAR, -1 FOR EXHAUSTED
11000		PUSH	P,[ORIGCNT]	
11100		PUSH	P,D			;NEW BP
11200		PUSHJ	P,ZADJST		;FIX UP STRING SPACE, PUT STRING ON STACK
11300		MOVEI	A,101
11400		POP	P,B			;MODE SETTING
11500		JSYS	SFMOD			;RESET
11600		MOVE	LPSA,X11
11700		JRST	RESTR			;AND RETURN
11800	
11900		BEND INTTY
12000	>;NOIMSSS
12100	
12200	ENDCOM(TT2)
     

00100	COMMENT ⊗ TTY FUNCTIONS ⊗
00200	
00300	
00400	DSCR TTY FUNCTIONS
00500	CAL SAIL
00600	⊗
00700	
00800	Comment ⊗
00900	INTEGER PROCEDURE INCHRW;
01000	 RETURN A CHAR FROM PBIN
01100	
01200	INTEGER PROCEDURE INCHRS;
01300	 RETURN -1 IF NO CHAR WAITING, ELSE FIRST CHAR (SIBE FOLLOWED BY PBIN)
01400	
01500	STRING PROCEDURE INCHWL;
01600	 WAIT FOR A LINE, THEN RETURN IT (PBINs, LINE EDITING)
01700	
01800	STRING PROCEDURE INCHSL(REFERENCE INTEGER FLAG);
01900	 FLAG←-1, STR←NULL IF NO LINE, ELSE FLAG←0, 
02000		STR←LINE (SIBE, FOLLOWED BY PBINs)
02100	
02200	STRING PROCEDURE INSTR(INTEGER BRCHAR);
02300	 RETURN ALL CHARS TO AND NOT INCLUDING BRCHAR (PBINs)
02400	
02500	STRING PROCEDURE INSTRL(INTEGER BRCHAR);
02600	 WAIT FOR ONE LINE, THEN DO INSTR (PBINs WITH EDITING)
02700	
02800	STRING PROCEDURE INSTRS(REFERENCE INTEGER FLAG; INTEGER BRCHAR);
02900	 FLAG←-1, STR←NULL IF NO LINES, ELSE FLAG←0, 
03000	  STR←INSTR(BRCHAR)
03100	
03200	
03300	PROCEDURE OUTCHR(INTEGER CHAR);
03400	 OUTPUT CHAR (PBOUT)
03500	
03600	PROCEDURE OUTSTR(STRING STR);
03700	 OUTPUT STR (SOUT)
03800	
03900	
04000	PROCEDURE CLRBUF;
04100	 CLEARS INPUT BUFFER (CFIBF)
04200	
04300	TTYIN, TTYINS, TTYINL (TABLE, @BRCHAR);
04400	 TTYIN WORKS WITH TTCALL 0'S; TTYINS DOES A SKIP
04500	 ON LINE FIRST, RETURNING NULL AND -1 IN BREAK IF NO LINES
04600	 TTYINL DOES A WAIT FOR LINE FIRST.
04700	 FULL BREAKSET CAPABILITIES EXCEPT FOR 
04800	 "R" MODE (AND OF COURSE, LINE NUM. STUFF)
04900	
05000		TITLE	TTYUUO
05100	⊗
05200	
05300	COMPIL(TTY,<PBIN,PBOUT,PSOUT,INCHRW,INCHRS,INCHWL,INCHSL,INSTR,OUTCHR,OUTSTR,INSTRL,INSTRS,CLRBUF,TTYIN,TTYINS,TTYINL,TTYUP
05400	>
05500		  ,<SAVE,RESTR,X11,X22,X33,INSET,CAT,STRNGC,GOGTAB,BRKMSK,.SKIP.,CTLOSW>
05600		  ,<TELETYPE FUNCTIONS>)
05700	;;#GF# DCS 2-1-72 (1-3) INCHWL BREAKS ON ALL ACTIVATION, TELLS WHICH IN .SKIP.
05800	; .SKIP. EXTERNAL ABOVE
05900	;;#GF#
06000	 
     

00100	HERE(PBIN)
00200	HERE (INCHRW)
00300		SETZM	CTLOSW		;INPUT REQUESTED
00400	INCHR1:	JSYS PBIN
00500		POPJ	P,
00600	
00700	HERE (INCHRS)
00800		SETZM	CTLOSW		;INPUT REQUESTED
00900		MOVEI	1,100
01000		JSYS SIBE
01100		   JRST	INCHR1
01200		SETO	1,		;RETURN -1
01300		POPJ	P,
01400	
01500	HERE(PBOUT)
01600	HERE (OUTCHR)	
01700		SKIPE	CTLOSW		;DOING OUTPUT?
01800		  JRST	OUTCRE		;NO
01900		EXCH	1,-1(P)		;GET PARAMETER, SAVING AC 1
02000		JSYS PBOUT			;OUTPUT CHAR	
02100		EXCH	1,-1(P)		;GET BACK 1	
02200	OUTCRE:	SUB	P,X22
02300		JRST	@2(P)		;RETURN
02400	
02500	
02600	HERE(PSOUT)
02700	HERE (OUTSTR)
02800		SKIPE	CTLOSW		;DOING OUTPUT?
02900		  JRST	[SUB SP,X22
03000			 POPJ P,
03100			]
03200		EXCH	2,(SP)		;BP WORD
03300		EXCH	3,-1(SP)	;LENGTH WORD
03400		PUSH	P,1		;ALSO NEED 1
03500		HRRZ	3,3		;COUNT
03600		JUMPE	3,NULSTR	;DONT SEND EMPTY STR
03700		MOVEI	1,101		;TERMINAL OUTPUT
03800		MOVN	3,3
03900		JSYS SOUT
04000	NULSTR:	POP	P,1
04100		POP	SP,2
04200		POP	SP,3		;ADJUSTS STACK AUTOMATICALLY
04300		POPJ 	P,		;RETURN
04400	
04500	;REDSTR (0) MARKS CTLOSW THAT INPUT WAS REQUESTED
04600	;(1) PREPARES TO MAKE A STRING OF 200 CHARS, 
04700	;(2) ZEROS C FOR COUNT
04800	;(3) SETS UP D WITH THE ORIGINAL BYTE-POINTER
04900	
05000	REDSTR:	SETZM	CTLOSW		;INPUT REQUESTED
05100		SKIPE	SGLIGN(USER)
05200		PUSHJ	P,INSET
05300		MOVEI	A,=200
05400		ADDM	A,REMCHR(USER)
05500		SKIPLE	REMCHR(USER)
05600		PUSHJ	P,STRNGC
05700		SETZ	C,		;COUNT HERE
05800		MOVE	D,TOPBYTE(USER)	;ORIGINAL BYTE-POINTER, IF NEEDED
05900		PUSH	SP,[0]		;NULL STRING IF NOTHING DONE
06000		PUSH	SP,TOPBYTE(USER)
06100		POPJ	P,
06200	
06300	FINSTR:	MOVEI	A,=200
06400		SUB	A,C		;NUMBER USED
06500		ADDM	A,REMCHR(USER)
06600		HRROM	C,-1(SP)	;STRING COUNT WORD
06700		MOVEM	D,TOPBYTE(USER)	;NEW TOPBYTE
06800		JRST	RESTR
06900	
07000	;CALL TO HERE WITH A PUSHJ TO GET A CHAR IN AC1
07100	;AC 3 HAS THE COUNT, D THE BYTE-POINTER
07200	EDICHR:
07300		JSYS PBIN			;GET A CHARACTER
07400		CAIN	1,DELLINE	;DELETE LINE CHAR
07500		   JRST	CTRLU
07600		CAIN	1,RUBCHAR	;RUBOUT?
07700		   JRST	RUBOUT
07800		CAIN	1,37		;PHONEY TENEX EOL?
07900		   MOVEI 1,12
08000		CAIN	1,33		;PHONEY TENEX ALTMODE?
08100		  MOVEI 1,ALTMODE	;DEC ALTMODE
08200		POPJ	P,		;GOOD CHAR FOR USER
08300		
08400	CTRLU:	
08500	;AC 1 IS FREE
08600		HRROI	1,[BYTE (7) 7,15,12,0,0]
08700		JSYS PSOUT	
08800		JUMPE	C,EDICHR	;IF NO CHARS THEN DO NOTHING
08900		SETZ	C,
09000		MOVE	D,TOPBYTE(USER)
09100		JRST	EDICHR
09200	
09300	RUBOUT:	JUMPE	C,CTRLU		;IF NO CHARS THEN DO CTRLU
09400	;AC 1 IS AVAILABLE
09500	IMSSS<
09600		MOVEI	1,101		;PRIMARY OUTPUT
09700		JSYS	DELCH
09800		  JFCL
09900		  JRST	DLTED		;DISPLAY -- LINE EMPTY
10000		  JRST	DLTED		;DISPLAY -- DELETE DONE
10100	>;IMSSS
10200		MOVEI	1,"\"
10300		JSYS PBOUT
10400		LDB	1,D		;GET LAST CHAR
10500		JSYS PBOUT			;AND SEND IT
10600	DLTED:
10700		SOJ	D,		;BACK UP BP TO LAST CHAR
10800		IBP	D
10900		IBP	D
11000		IBP	D
11100		IBP	D
11200		SOJA	C,EDICHR	;AND GET ANOTHER CHAR
11300	
11400	HERE(INSTRL)
11500	HERE (INSTR) 
11600		PUSHJ	P,SAVE
11700		PUSHJ	P,REDSTR
11800		MOVE	B,-1(P)		;BREAK CHAR
11900		MOVE	LPSA,X22	;# TO REMOVE
12000	
12100	INS1:	CAIL	C,=200		;COUNT EXHAUSTED?
12200		 JRST	FINSTR		;YES
12300	INS2:	PUSHJ	P,EDICHR	;GET A CHAR IN 1, USING EDITING
12400		CAMN	1,B		;BREAK?
12500		 JRST	 FINSTR		; YES, ALL DONE
12600		IDPB	1,D		;PUT IT AWAY AND
12700		AOJA	C,INS1
12800	
12900	HERE (INCHWL)	PUSHJ	P,SAVE
13000		PUSHJ	P,REDSTR
13100		MOVE	LPSA,X11
13200	
13300	INS3:	CAIL	C,=200		;COUNT EXHAUSTED?
13400		  JRST	DNSTR1		;YES
13500		PUSHJ	P,EDICHR	;GET A CHAR
13600		CAIE	1,ALTMODE
13700		CAIN	1,12
13800		   JRST	DNSTR
13900		CAIN	1,15		;CR?	
14000		   JRST	INS3		;IGNORE
14100		IDPB	1,D		;PUT IT AWAY AND
14200		AOJA	C,INS3		;NEXT CHARACTER
14300	
14400	DNSTR:	MOVEM	1,.SKIP.	;SET BREAK CHAR
14500		JRST	FINSTR
14600	DNSTR1:	SETOM	.SKIP.		;INDICATE COUNT EXHAUSTED
14700		JRST	FINSTR
14800	
14900	
15000	HERE (INCHSL)	PUSHJ	P,SAVE
15100		MOVE	LPSA,X22	;PARAM (FLAG) AND RETURN
15200		PUSHJ	P,REDSTR
15300		SETOM	@-1(P)		;ASSUME FAILED
15400		MOVEI	1,100		;PRIMARY INPUT
15500		JSYS SIBE			;CHARACTERS WAITING?
15600		    SKIPA		;YES
15700		JRST	FINSTR		;NO, FIX UP AND RETURN
15800		SETZM	@-1(P)
15900		JRST	INS3		;AND USE INCHWL'S LOOP
16000	
16100		
16200	HERE(INSTRS)
16300		PUSHJ	P,SAVE
16400		MOVE	LPSA,X33
16500		PUSHJ	P,REDSTR
16600		SETOM	@-2(P)		;ASSUME FAILED
16700		MOVEI	1,100		;RIMARY INPUT
16800		JSYS SIBE			;CHARACTERS WAITING
16900		   SKIPA		;YES
17000		JRST	FINSTR		;NO, FIX UP AND RETURN	
17100		SETZM	@-2(P)		;INDICATE SUCCESS
17200		MOVE	B,-1(P)		;GET BREAK CHARACTER	
17300		JRST	INS2
17400	
17500	HERE (CLRBUF)
17600		PUSH	P,1
17700		MOVEI	1,100		;PRIMARY INPUT
17800		JSYS CFIBF			;CLEAR BUFFER
17900		POP	P,1
18000		POPJ	P,
18100	
18200	HERE (TTYINS) PUSHJ	P,SAVE
18300		PUSHJ	P,REDSTR	;PREPARE TO MAKE A STRING
18400		MOVE	LPSA,X33
18500		SETOM	@-1(P)		;ASSUME NO CHARS
18600		MOVEI	1,100		;PRIMARY INPUT
18700		JSYS SIBE			;CHARS WAITING?
18800		   SKIPA		;YES
18900		JRST	FINSTR		;NONE WAITING
19000		JRST	TYIN1		;GO AHEAD
19100	
19200	
19300	HERE(TTYINL)
19400	HERE (TTYIN)	PUSHJ	P,SAVE
19500	TYIN:	PUSHJ	P,REDSTR		;PREPARE STACK,A,STRNGC FOR A STRING
19600		MOVE	LPSA,X33		;PREPARE TO RETURN
19700	TYIN1:	SETZM	@-1(P)		;ASSUME NO BREAK CHAR
19800		MOVE	X,-2(P)		;TABLE #
19900		MOVEI	TEMP,-1		;BLOCK MUST BE THERE AND TABLE MUST BE INIT'ED
20000		PUSHJ	P,BKTCHK		;CHECK TABLE #
20100		 JRST	FINSTR		;ERROR
20200		MOVE	FF,BRKMSK(CHNL)	;BITS FOR THIS TABLE
20300		ADD	CHNL,CDB	;RELOCATE RANGE 1 TO 18
20400		MOVEI	Z,1		;FOR TESTING LINE NUMBERS
20500		SKIPN	LINTBL(CHNL)	;DON'T LET TEST SUCCEED IF
20600		 MOVEI	 Z,0		;WE'RE TO LET LINE NUMBERS THRU
20700		MOVE	Y,CDB
20800		ADD	Y,[XWD 1,BRKTBL] ;BRKTBL+RLC(CDB)
20900	TTYN:	CAIL	C,=200		;COUNT EXCEEDED?
21000		   JRST	FINSTR		;YES
21100		PUSHJ	P,EDICHR	;GET A CHAR
21200	TTYN1:	TDNE	FF,@Y		;BREAK OR OMIT?
21300		JRST	TTYSPC		; YES, FIND OUT WHICH
21400	TTYC:	IDPB	1,D		;PUT IT AWAY
21500		AOJA	C,TTYN		;COUNT AND CONTINUE
21600		JRST	FINSTR		;DONE
21700	TTYSPC:	HLLZ	TEMP,@Y		;WHICH?
21800		TDNN	TEMP,FF
21900		JRST	TTYN		;OMIT
22000		MOVEM	1,@-1(P)
22100		SKIPN	Y,DSPTBL(CHNL)	;WHAT TO DO WITH IT
22200		JRST	FINSTR		;DONE, NO SAVE
22300		JUMPL	Y,TTYAPP	;APPEND
22400		PUSH	P,1		;SAVE 
22500		MOVEI	1,100		;PRIMARY INPUT
22600		JSYS BKJFN
22700		  ERR	<CAN'T RETAIN BREAK CHAR FROM TTYIN>,1
22800		POP	P,1
22900		JRST	FINSTR		;AND RETURN
23000	TTYAPP:	IDPB	1,D		;COUNT THE BREAK CHAR
23100		ADDI	C,1		;ONE MORE HAPPY CHAR
23200		JRST	FINSTR
23300	
23400	
23500	DSCR INTEGER PROCEDURE TTYUP(INTEGER NEWVALUE)
23600	
23700		Using the RFMOD and SFMOD jsyses, sets lower-to-upper
23800	case conversion to NEWVALUE, returning the oldvalue.  Tests
23900	and modifies bit 31 of the RFMOD word for the primary input
24000	file.	
24100	⊗;
24200	HERE(TTYUP)
24300		PUSHJ	P,SAVE
24400		MOVE	LPSA,X22		;SET FOR RETURN
24500		MOVEI	A,101			;PRIMARY INPUT FILE
24600		JSYS	RFMOD			;GET THE CURRENT SETTINGS
24700		SETZ	C,			;ASSUME NOT CURRENTLY SET
24800		TRNE	B,1B31			;IS IT SET?
24900		  SETO	C,			;IT WAS
25000		MOVEM	C,RACS+A(USER)	
25100		MOVE	C,[TRO B,1B31]		;ASSUME WE WANT TO SET UP
25200		SKIPN	-1(P)			;DID WE REALLY?
25300		  MOVE	C,[TRZ B,1B31]		;NO, DONT
25400		XCT	C
25500		JSYS	STPAR
25600		JRST	RESTR			;AND RETURN
25700	
25800	
25900	ENDCOM(TTY)
26000	COMPIL(PTY)
26100	ENDCOM(PTY)
26200	
26300	COMPIL(FIL,<FILNAM>,<FLSCAN,X22>,<FILNAM SCANNING ROUTINE>)
     

00100	COMMENT ⊗Filnam ⊗
00200	
00300	DSCR FILNAM
00400	CAL PUSHJ
00500	PAR file name string on SP stack
00600	 of form FILENAME<.EXT><[PROJ,PROG]>
00700	RES FNAME(USER) : SIXBIT /filename/
00800	 EXT(USER): SIXBIT /extension,,0/
00900	 0
01000	 PRPN(USER): SIXBIT /PRJ PRG/ (or zero)
01100	SID uses D,X,Y (4-6), REMOVES STRING FROM STACK
01200	⊗
01300	
01400	↑↑FILNAM:
01500		SUB	SP,X22		;ADJUST STACK
01600		FOR II←1,3 <
01700		SETZM	FNAME+II(USER)>
01800		MOVEI	X,FNAME(USER)	;WHERE TO PUT IT
01900		PUSHJ	P,FLSCAN	;GET FILE NAME
02000		JUMPE	Y,FLDUN	;FILE NAME ONLY
02100		CAIE	Y,"."		;EXTENSION?
02200		JRST	FLEXT		;NO, CHECK PPN
02300		MOVEI	X,FNAME+1(USER)
02400		PUSHJ	P,FLSCAN
02500	FLEXT:	JUMPE	Y,FLDUN	;NO PPN SPECIFIED
02600		CAIE	Y,"["
02700		JRST	FLERR		;INVALID CHARACTER
02800		PUSHJ	P,[
02900	
03000		RJUST:	SETZM	PROJ(USER)
03100			MOVEI	X,PROJ(USER)
03200			PUSHJ	P,FLSCAN	;GET PROJ OR PROG IN SIXBIT
03300	IFN SIXSW,<
03400			MOVE	X,PROJ(USER)
03500			IMULI	D,-6		;SHIFT FACTOR
03600			LSH	X,(D)		;RIGHT-JUSTIFY THE PROJ OR PROG
03700	>;IF SIXSW (SET IN HEAD, USUALLY CONDITIONED ON NOEXPO)
03800		
03900	IFE SIXSW,<
04000			MOVEI	X,0
04100	;;#GT# DCS 5-11-72 ALLOW LARGE OCTAL NUMBERS AT STD DEC SYSTEMS
04200			MOVE	D,PROJ(USER)	;WAS A HLLZ
04300	;;
04400		FBACK:	MOVEI	C,0
04500			LSHC	C,6		;GET A SIXBIT CHAR
04600			CAIL	C,'0'
04700			CAILE	C,'7'
04800			JRST	FLERR		;INVALID OCTAL
04900			LSH	X,3
05000			IORI	X,-'0'(C)
05100			JUMPN	D,FBACK
05200	>;NOT SIXSW (USUALLY CONDITIONED ON EXPO)
05300		FPOP:	POPJ	P,]
05400	
05500		HRLZM	X,FNAME+3(USER)
05600		CAIE	Y,","
05700		JRST	FLERR		;INVALID CHAR
05800		PUSHJ	P,RJUST		;JUSTIFY(AND CONVERT IF EXPORT) PROG #
05900		HRRM	X,FNAME+3(USER)
06000		CAIN	Y,"]"
06100	FLDUN:	AOS	(P)		;SUCCESSFUL
06200	FLERR:	POPJ	P,		;DONE, NOT NECESSARILY RIGHT
06300	
06400	ENDCOM(FIL)
06500	COMPIL(FLS,<FLSCAN>,,<FLSCAN ROUTINE>)
     

00100	COMMENT ⊗Flscan ⊗
00200	
00300	DSCR FLSCAN
00400	CAL PUSHJ
00500	PAR X -- addr of destination SIXBIT
00600	 1(SP), 2(SP) -- input string
00700	RES sixbit for next filename, etc in word addressed by X
00800	 break (punctuation) char in Y (0 if string exhausted)
00900	 D,X, input string adjusted
01000	SID only those AC changes listed above (Y, for instance)
01100	⊗
01200	
01300	↑↑FLSCAN:  
01400		HRRZS	1(SP)		;WANT ONLY LENGTH PART
01500		MOVEI	D,6		;MAX NUMBER PICKED UP
01600		SETZM	(X)		;ZERO DESTINATION
01700		HRLI	X,440600	;BYTE POINTER NOW
01800	FLN1:	MOVEI	Y,0		;ASSUME NO STRING LEFT
01900		SOSGE	1(SP)		;TEST 0-LENGTH STRING
02000		 POPJ	 P,
02100		ILDB	Y,2(SP)		;GET BYTE
02200		CAIE	Y,"."		;CHECK VALID BREAK CHAR
02300		CAIN	Y,"["
02400		POPJ	P,
02500		CAIE	Y,"]"
02600		CAIN	Y,","
02700		POPJ	P,
02800		JUMPE	D,FLN1		;NEED NO MORE CHARS
02900		TRZN	Y,100		;MOVE 100 BIT TO 40 BIT
03000		TRZA	Y,40		; TO CONVERT TO SIXBIT
03100		TRO	Y,40		; (NO CHECKING)
03200		IDPB	Y,X		;PUT IT AWAY
03300		SOJA	D,FLN1		;CONTINUE
03400	
03500	ENDCOM(FLS)
     

00100	COMPIL(CAS,<CSERR,LPRYER>,<GOGTAB>
00200		  ,<CSERR, LPRYER -- SUPPORT ROUTINES>)
00300	HERE(CSERR)	MOVE	USER,GOGTAB
00400		POP	P,UUO1(USER)	;STANDARD PLACE
00500		ERR	<CASE INDEX OVERFLOW, VALUE IS >,13
00600		JRST	@UUO1(USER)	;RETURN OK
00700	
00800	HERE (LPRYER) ERR	<DATUM OF ARRAY NOT THERE>,1
00900		POPJ	P,
01000	
01100	ENDCOM(CAS)
01200	
01300	
01400	IFN ALWAYS, <BEND IOSER>
01500	DSCR BEND IOSER ⊗
01600	>;TENX
     

     

00100	
00200	
00300	
00400	
00500	
00600	
00700	
     

00100	
00200	
00300	
00400	
00500	
00600	
00700	
     

00100	
     

00100